页面缓存的原理:

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

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

存在的问题:

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

实现代码:

  1. @Controller
  2. @RequestMapping("/goods")
  3. public class GoodsController {
  4.  
  5. @Autowired
  6. private MiaoshaUserService miaoshaUserService;
  7.  
  8. @Autowired
  9. private GoodsService goodsService;
  10.  
  11. @Autowired
  12. private RedisService redisService;
  13.  
  14. @Autowired
  15. private ThymeleafViewResolver thymeleafViewResolver;
  16.  
  17. @Autowired
  18. ApplicationContext applicationContext;
  19.  
  20. @RequestMapping(value = "/to_list",produces = "text/html")
  21. @ResponseBody
  22. public String list(Model model, MiaoshaUser user, HttpServletRequest request,HttpServletResponse response){
  23.  
  24. model.addAttribute("user",user);
  25.  
  26. String html = redisService.get(GoodsKey.getGoodsList, "", String.class);
  27. if(!StringUtils.isEmpty(html)){
  28. System.out.println("从缓存中取");
  29. return html;
  30. }
  31.  
  32. List<GoodsVo> goodsList = goodsService.listGoodsVo();
  33.  
  34. model.addAttribute("goodsList",goodsList);
  35.  
  36. SpringWebContext ctx = new SpringWebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext);
  37.  
  38. //手动渲染
  39. html = thymeleafViewResolver.getTemplateEngine().process("goods_list", ctx);
  40.  
  41. if(!StringUtils.isEmpty(html)){
  42. redisService.set(GoodsKey.getGoodsList,"",html);
  43. }
  44. System.out.println("从数据库中取");
  45. return html;
  46. }
  47.  
  48. @RequestMapping(value = "/to_detail/{goodsId}", produces = "text/html")
  49. @ResponseBody
  50. public String detail(HttpServletRequest request,HttpServletResponse response,Model model, MiaoshaUser user,
  51. @PathVariable("goodsId") long goodsId){
  52.  
  53. model.addAttribute("user",user);
  54.  
  55. String html=redisService.get(GoodsKey.getGoodsDetail,""+goodsId,String.class);
  56. if(!StringUtils.isEmpty(html)){
  57. System.out.println("从缓存中取");
  58. return html;
  59. }
  60. GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
  61. model.addAttribute("goods", goods);
  62.  
  63. //得到秒杀的开始时间、结束时间、以及当前时间
  64. long startAt = goods.getStartDate().getTime();
  65. long endAt = goods.getEndDate().getTime();
  66. long now = System.currentTimeMillis();
  67.  
  68. //设置剩余时间
  69. int remainSeconds=0;
  70.  
  71. //设置秒杀状态
  72. int miaoshaStatus=0;
  73.  
  74. //判断
  75. if(now<startAt){
  76. //秒杀还没开始
  77. miaoshaStatus=0;
  78. remainSeconds= (int) ((startAt-now)/1000);
  79. }else if(now>endAt){
  80. //秒杀已经结束
  81. miaoshaStatus=2;
  82. remainSeconds=-1;
  83. }else {
  84. //秒杀正在进行
  85. miaoshaStatus=1;
  86. remainSeconds=0;
  87. }
  88.  
  89. model.addAttribute("miaoshaStatus",miaoshaStatus);
  90. model.addAttribute("remainSeconds",remainSeconds);
  91.  
  92. SpringWebContext ctx = new SpringWebContext(request,response,request.getServletContext(),request.getLocale(),model.asMap(),applicationContext);
  93.  
  94. //手动渲染
  95. html = thymeleafViewResolver.getTemplateEngine().process("goods_detail", ctx);
  96.  
  97. if(!StringUtils.isEmpty(html)){
  98. redisService.set(GoodsKey.getGoodsDetail,""+goodsId,html);
  99. }
  100. System.out.println("从数据库中取");
  101. return html;
  102. }
  103. }

对象缓存:

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

  1. public MiaoshaUser getById(long id){
  2.  
  3. MiaoshaUser user = redisService.get(MiaoshaUserKey.getById, ""+id, MiaoshaUser.class);
  4. if(user!=null){
  5. System.out.println("从缓存取");
  6. return user;
  7. }
  8. user = miaoshaUserDao.getById(id);
  9. if(user!=null){
  10. redisService.set(MiaoshaUserKey.getById,""+id,user);
  11. }
  12. System.out.println("从数据库取");
  13. return user;
  14. }

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

这里有一篇博客写的很好

比如一个修改密码的方法

  1. public boolean updatePassword(String token, long id, String formPass){
  2. //取出user
  3. MiaoshaUser user = getById(id);
  4. if(user==null){
  5. throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
  6. }
  7.  
  8. user.setPassword(MD5Util.formPassToDBPass(formPass,user.getSalt()));
  9.  
  10. //更新数据库
  11. miaoshaUserDao.update(user);
  12.  
  13. //处理缓存,
  14. redisService.delete(MiaoshaUserKey.getById,""+id);
  15. redisService.set(MiaoshaUserKey.token,token,user);
  16.  
  17. return true;
  18. }
 

java初探(1)之缓存技术的更多相关文章

  1. memcached缓存技术

    初学memcached缓存技术,如果文章写得不好还请谅解 应用环境:win7 实现环境:cmd,eclipse Memcached简洁而强大.它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存 ...

  2. (转)java缓存技术,记录

    http://blog.csdn.net/madun/article/details/8569860 最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇 ...

  3. JAVA缓存技术之EhCache

    最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考.此为转贴,帖子来处:http://cogipard.info/ar ...

  4. JAVA缓存技术之EhCache(转)

    最近再ITEYE上看到关于讨论JAVA缓存技术的帖子比较多,自己不懂,所以上网大概搜了下,找到一篇,暂作保存,后面如果有用到可以参考.此为转贴,帖子来处:http://cogipard.info/ar ...

  5. JAVA几种缓存技术介绍说明

    OSCache OSCache是个一个广泛采用的高性能的J2EE缓存框架,OSCache能用于任何Java应用程序的普通的缓存解决方案. OSCache有以下特点: 我创建了一个群,群里不定期分享技术 ...

  6. java中的缓存技术该如何实现

    1缓存为什么要存在?2缓存可以存在于什么地方?3缓存有哪些属性?4缓存介质? 搞清楚这4个问题,那么我们就可以随意的通过应用的场景来判断使用何种缓存了. 1. 缓存为什么要存在?一 般情况下,一个网站 ...

  7. java缓存技术的介绍

    一.什么是缓存1.Cache是高速缓冲存储器 一种特殊的存储器子系统,其中复制了频繁使用的数据以利于快速访问2.凡是位于速度相差较大的两种硬件/软件之间的,用于协调两者数据传输速度差异的结构,均可称之 ...

  8. 干货|java缓存技术详解

    一.缓存是什么? 请点击此处输入图片描述 Cache ①高速缓冲存储器,其中复制了频繁使用的数据以利于快速访问. ②位于速度相差较大的两种硬件/软件之间,用于协调两者数据传输速度差异的结构 二.缓存有 ...

  9. java初探(1)之静态页面化——客户端缓存

    利用服务端缓存技术,将页面和对象缓存在redis中,可以减少时间浪费,内存开销.但在每次请求的过程中,仍然会有大量静态资源的请求和返回. 使用静态页面技术,页面不必要使用页面交互技术,比如thymel ...

  10. 网站缓存技术总结( ehcache、memcache、redis对比)

    网站技术高速发展的今天,缓存技术已经成为大型网站的一个关键技术,缓存设计好坏直接关系的一个网站访问的速度,以及购置服务器的数量,甚至影响到用户的体验. 网站缓存按照存放的地点不同,可以分为客户端缓存. ...

随机推荐

  1. 15、Java中级进阶 面向对象 继承

    1.何为面向对象 其本质是以建立模型体现出来的抽象思维过程和面向对象的方法(百度百科)是一种编程思维,也是一种思考问题的方式 如何建立面向对象的思维呢?1.先整体,再局部2.先抽象,再具体3.能做什么 ...

  2. idea中GitPush失败问题

    首先是你的项目中有和和历史不符的东西 Push rejected: Push to *****/***** was rejected 推拒绝:推送到起源/主人被拒绝 直接是解决办法,直接打开你要上传代 ...

  3. HRNet

  4. Qt之先用了再说系列-多线程方式2

    继Qt之先用了再说系列-多线程方式2 本次说说在Qt里多线程使用第2种方式,也是qt官方比较推荐用的方式,相对与直接继承QThread 重写run方法中灵活了一些,如果第一次使用可能会转不湾来,没有直 ...

  5. Tun/Tap接口使用指导

    Tun/Tap接口指导 目录 Tun/Tap接口指导 概述 工作机制 创建接口 举例 简单的程序 隧道 拓展 参考 概述 对tun接口的了解需求主要来自于openshift的网络,在openshift ...

  6. CODING DevOps 微服务项目实战系列第一课,明天等你

    CODING DevOps 微服务项目实战系列第一课<DevOps 微服务项目实战:DevOps 初体验>将由 CODING DevOps 开发工程师 王宽老师 向大家介绍 DevOps ...

  7. python数据类型分类(可变(不可变)数据类型)

    一:python数据类型的分类: 可变(不可哈希)的数据类型: list 列表 dict 字典 set 集合 不可变(可哈希)的数据类型: str 字符串 bool 布尔型 int 整型 tuple ...

  8. ls-remote -h -t git://github.com/adobe-webplatform/eve.git 报错问题

    npm ERR! Error while executing:npm ERR! D:\开发工具\git\Git\cmd\git.EXE ls-remote -h -t git://github.com ...

  9. Jmeter 常用函数(14)- 详解 __strLen

    如果你想查看更多 Jmeter 常用函数可以在这篇文章找找哦 https://www.cnblogs.com/poloyy/p/13291704.htm 作用 读取给定字符串的长度 语法格式 ${__ ...

  10. 计算机网络-链路层(4)WiFi:802. 11无线LAN

    有几套有关无线LAN 的802. 11标准,包括802.11b.802.11a和802.11g. 802.11g是至今为止最为流行的技术.一些双模式(802.11a/g)和三模式(802.11a/b/ ...