java初探(1)之缓存技术

页面缓存的原理:

普通要想生成一个页面,需要该页面在springboot的templates目录下,然后通过springboot的内部渲染,视图解析器将页面渲染回客户端,这中间会花费很长的时间。

但如果将整个页面的代码转化为字符串,存到redis中,当请求一个页面时,通过ResponseBody注解,将该字符串直接返回,由客户端自己渲染成页面,那么服务器的压力就会小很多,有效的解决并发。

存在的问题:

需要合理设置redis缓存的时间,如果设置时间太长,会导致当页面数据本该变化的时候却没有改变,因为缓存的一定是一个静态页面。

实现代码:

@Controller
@RequestMapping("/goods")
public class GoodsController {

    @Autowired
    private MiaoshaUserService miaoshaUserService;

    @Autowired
    private GoodsService goodsService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private ThymeleafViewResolver thymeleafViewResolver;

    @Autowired
    ApplicationContext applicationContext;

    @RequestMapping(value = "/to_list",produces = "text/html")
    @ResponseBody
    public String list(Model model, MiaoshaUser user, HttpServletRequest request,HttpServletResponse response){

        model.addAttribute("user",user);

        String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
        if(!StringUtils.isEmpty(html)){
            System.out.println("从缓存中取");
            return html;
        }

        List<GoodsVo> goodsList = goodsService.listGoodsVo();

        model.addAttribute("goodsList",goodsList);


        SpringWebContext  ctx = new SpringWebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext);

        //手动渲染
        html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);



        if(!StringUtils.isEmpty(html)){
            redisService.set(GoodsKey.getGoodsList,"",html);
        }
        System.out.println("从数据库中取");
        return html;
    }

    @RequestMapping(value = "/to_detail/{goodsId}", produces = "text/html")
    @ResponseBody
    public String detail(HttpServletRequest request,HttpServletResponse response,Model model, MiaoshaUser user,
                         @PathVariable("goodsId") long goodsId){

        model.addAttribute("user",user);


        String html=redisService.get(GoodsKey.getGoodsDetail,""+goodsId,String.class);
        if(!StringUtils.isEmpty(html)){
            System.out.println("从缓存中取");
            return html;
        }
        GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
        model.addAttribute("goods", goods);

        //得到秒杀的开始时间、结束时间、以及当前时间
        long startAt = goods.getStartDate().getTime();
        long endAt = goods.getEndDate().getTime();
        long now = System.currentTimeMillis();

        //设置剩余时间
        int remainSeconds=0;

        //设置秒杀状态
        int miaoshaStatus=0;

        //判断
        if(now<startAt){
            //秒杀还没开始
            miaoshaStatus=0;
            remainSeconds= (int) ((startAt-now)/1000);
        }else if(now>endAt){
            //秒杀已经结束
            miaoshaStatus=2;
            remainSeconds=-1;
        }else {
            //秒杀正在进行
            miaoshaStatus=1;
            remainSeconds=0;
        }

        model.addAttribute("miaoshaStatus",miaoshaStatus);
        model.addAttribute("remainSeconds",remainSeconds);

        SpringWebContext  ctx = new SpringWebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext);

        //手动渲染
        html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);

        if(!StringUtils.isEmpty(html)){
            redisService.set(GoodsKey.getGoodsDetail,""+goodsId,html);
        }
        System.out.println("从数据库中取");
        return html;
    }
}

对象缓存:

对象缓存,如果只是查询某个对象,则比较简单,判断缓存中有没有对象,如果有就返回,如果没有就从数据库中取到,然后放入缓存中,然后返回。

public MiaoshaUser getById(long id){

        MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);
        if(user!=null){
            System.out.println("从缓存取");
            return user;
        }
        user = miaoshaUserDao.getById(id);
        if(user!=null){
            redisService.set(MiaoshaUserKey.getById,""+id,user);
        }
        System.out.println("从数据库取");
        return user;
    }

如果涉及到修改对象中的某个值,则需要做的事情比较多,考虑到有并发的存在,因此,我们需要先修改数据库的内容,然后修改缓存的内容。

这里有一篇博客写的很好

比如一个修改密码的方法

public boolean updatePassword(String token, long id, String formPass){
        //取出user
        MiaoshaUser user = getById(id);
        if(user==null){
            throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
        }


        user.setPassword(MD5Util.formPassToDBPass(formPass,user.getSalt()));

        //更新数据库
        miaoshaUserDao.update(user);

        //处理缓存,
        redisService.delete(MiaoshaUserKey.getById,""+id);
        redisService.set(MiaoshaUserKey.token,token,user);

        return true;
    }
 

相关推荐