zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    View Code

    对象缓存:

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

    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;
        }
     
  • 相关阅读:
    精灵点点基础教程1 -- 下载与安装
    技术人员搞公司还是省省吧
    企业级自定义表单引擎解决方案(二)--架构及核心模块设计
    企业级自定义表单引擎解决方案(一)--总体介绍
    .net core quartz job作业调度管理组件
    NPOI读写Excel组件封装Excel导入导出组件
    企业级工作流解决方案(十七)--工作流--工作流插件模型
    企业级工作流解决方案(十六)--工作流--工作流实体模型
    企业级工作流解决方案(十五)--集成Abp和ng-alain--Abp其他改造
    企业级工作流解决方案(十四)--集成Abp和ng-alain--自动化脚本
  • 原文地址:https://www.cnblogs.com/lovejune/p/12342672.html
Copyright © 2011-2022 走看看