SpringBoot + Redis +SpringSession 缓存之实战

前言

前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需要消耗一定时间的,就是从某种程度上讲短暂的缓存不一致依旧存在。
所以,我就选择了集中式缓存,在 SpringBoot 工程中使用 Redis 进行缓存。

个人参考案例

个人博客 : https://zggdczfr.cn/
个人参考案例(如果认可的话,麻烦给颗star) : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B10

(一)Spring Boot + Redis

1. 安装 Redis

Redis 原本是不支持在 Window 操作系统安装运行的,但后来有了 Window 支持,放上链接(具体安装百度一下就有): https://github.com/MSOpenTech/redis/releases
注意:建议使用 2.8+ 以上Reids版本,不然会与 SpringSeeeion 产生冲突!

2. 添加依赖

新建一个SpringBoot工程,配置MyBatis+Druid。在pom.xml文件中添加Redis缓存支持。

  1. <!-- 缓存依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-cache</artifactId>
  5. </dependency>
  6. <!-- spring boot redis 依赖 -->
  7. <dependency>
  8. <groupId>org.springframework.boot</groupId>
  9. <artifactId>spring-boot-starter-redis</artifactId>
  10. </dependency>
3. application.properties 配置

有关于 Redis 配置参数:

  1. # Redis 配置(默认配置)
  2. # Redis 数据库索引(默认为0)
  3. spring.redis.database=0
  4. # Redis 服务器地址
  5. spring.redis.host=localhost
  6. # Redis 服务器端口
  7. spring.redis.port=6379
  8. # Redis 服务器密码(默认为空)
  9. spring.redis.password=
  10. # 连接池最大连接数(使用负值表示没有限制)
  11. spring.redis.pool.max-active=8
  12. # 连接池中的最大空闲连接
  13. spring.redis.pool.max-idle=8
  14. # 连接池中的最小空闲连接
  15. spring.redis.pool.min-idle=0
  16. # 连接池最大阻塞等待时间(使用负值表示没有限制)
  17. spring.redis.pool.max-wait=-1
  18. # 设置连接超时
  19. spring.redis.timeout=0
4. 关于 SpringBoot 缓存注解

在支持 Spring Cache 的环境下,

  • @EnableCaching : 开启SpringBoot缓存策略,放在启动主类。
  • @CacheConfig(cacheNames = "XXX") : 设置一个名为”XXX”的缓存空间。
  • @Cacheable : Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。
  • @CacheEvict : 清除缓存。
  • @CachePut : @CachePut也可以声明一个方法支持缓存功能。使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。
5. 添加 Redis 配置类

重要参考资料 : http://www.jianshu.com/p/a2ab17707eff
这个类主要是为Redis添加序列化工具,这一点 SpringBoot 并没有帮我们封装好(或者我没有找到)。

  1. @Configuration
  2. @EnableCaching
  3. public class RedisConfig extends CachingConfigurerSupport {
  4.  
  5. @Value("${spring.redis.host}")
  6. private String host;
  7. @Value("${spring.redis.port}")
  8. private int port;
  9. @Value("${spring.redis.timeout}")
  10. private int timeout;
  11.  
  12. @Bean
  13. public KeyGenerator wiselyKeyGenerator(){
  14. return new KeyGenerator() {
  15. @Override
  16. public Object generate(Object o, Method method, Object... objects) {
  17. StringBuilder sb = new StringBuilder();
  18. sb.append(o.getClass().getName());
  19. sb.append(method.getName());
  20. for (Object obj : objects){
  21. sb.append(obj.toString());
  22. }
  23. return sb.toString();
  24. }
  25. };
  26. }
  27.  
  28. @Bean
  29. public JedisConnectionFactory redisConnectionFactory(){
  30. JedisConnectionFactory factory = new JedisConnectionFactory();
  31. factory.setHostName(host);
  32. factory.setPort(port);
  33. factory.setTimeout(timeout); //设置连接超时
  34. return factory;
  35. }
  36.  
  37. @Bean
  38. public CacheManager cacheManager(RedisTemplate redisTemplate){
  39. RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
  40. cacheManager.setDefaultExpiration(10); //设置 key-value 超时时间
  41. return cacheManager;
  42. }
  43.  
  44. @Bean
  45. public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
  46. StringRedisTemplate template = new StringRedisTemplate(factory);
  47. setSerializer(template); //设置序列化工具,就不必实现Serializable接口
  48. template.afterPropertiesSet();
  49. return template;
  50. }
  51.  
  52. private void setSerializer(StringRedisTemplate template){
  53. Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
  54. ObjectMapper om = new ObjectMapper();
  55. om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
  56. om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
  57. jackson2JsonRedisSerializer.setObjectMapper(om);
  58. template.setValueSerializer(jackson2JsonRedisSerializer);
  59. }
  60. }
其它

其他代码就不累赘贴出来了,直接参考一下我的Github仓库 : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B10
启动工程后,访问 http://localhost:8080/redis ,我们可以在控制台看到以下结果:

  1. 没有走缓存!8b10aba26bd5402bbdad2584d8452f1f
  2. User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='张三', age=20}
  3. User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='张三', age=20}
  4. ====== 修改 Redis 缓存数据 ======
  5. User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='李四', age=18}
  6. User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='李四', age=18}

补充:若还是不太了解的话,可以查看一下我的上一篇博客spring boot学习(十三)SpringBoot缓存(EhCache 2.x 篇),里面利用了Log4j的debug模式详细打印了执行过的SQL语句,或者利用Druid控制台来查看SQL语句的执行情况。

(二)Spring Session

分布式系统中,sessiong共享有很多的解决方案,其中托管到缓存中应该是最常用的方案之一。

SpringSession 原理

@EnableRedisHttpSession 这个注解创建了一个名为 springSessionRepositoryFilter 的 bean,负责替换 httpSession,同时由 redis 提供缓存支持。
maxInactiveIntervalInSeconds:设置Session失效时间。使用Redis Session之后,原Boot的server.session.timeout属性不再生效。

1. 添加 SpringSession 配置类
  1. @Configuration
  2. @EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
  3. public class HttpSessionConfig {
  4. // 默认无配置
  5. }

2. 添加验证的URL接口

  1. @Value("${server.port}")
  2. String port;
  3.  
  4. @RequestMapping(value = "/session", method = RequestMethod.GET)
  5. public Object getSession(HttpServletRequest request){
  6. Map<String, Object> map = new HashMap<String, Object>();
  7. map.put("SessionId", request.getSession().getId());
  8. map.put("ServerPort", "服务端口号为 "+port);
  9. return map;
  10. }

同时启动两个相同的工程(比如:8080端口与9090端口),访问 http://localhost:8080/sessionhttp://localhost:9090/session
我们可以得到以下结果:

  1. {"SessionId":"01f353e1-5cd3-4fbd-a5d0-9a73e17dcec2","ServerPort":"服务端口号为 8080"}
  2.  
  3. {"SessionId":"01f353e1-5cd3-4fbd-a5d0-9a73e17dcec2","ServerPort":"服务端口号为 9090"}

结果中的SessionId是一致的,却是由两个不同项目工程来提供服务。这样子,SpringSession 利用拦截器 Filter 帮我们在每个请求前进行了同步设置,达到了分布式系统中 session 共享。

spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战的更多相关文章

  1. spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法

    spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法 前言 本篇接着<spring boot / cloud ...

  2. spring boot 学习(十)SpringBoot配置发送Email

    SpringBoot配置发送Email 引入依赖 在 pom.xml 文件中引入邮件配置: <dependency> <groupId>org.springframework. ...

  3. Spring Boot (十四): 响应式编程以及 Spring Boot Webflux 快速入门

    1. 什么是响应式编程 在计算机中,响应式编程或反应式编程(英语:Reactive programming)是一种面向数据流和变化传播的编程范式.这意味着可以在编程语言中很方便地表达静态或动态的数据流 ...

  4. spring boot 学习10 定义springboot的两种方法

    使用spring boot的两种方法: A:继承spring-boot-starter-parent项目 这种方式很简单,只需要在POM里面添加parent父工程即可. B: 如果你不喜欢继承spri ...

  5. spring Boot 学习(四、Spring Boot与任务)

    一.异步任务 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在 处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用 多线程来完成此类任务,其实,在Spri ...

  6. Spring Boot学习(四)常用注解

    一.注解对照表 注解 使用位置 作用  @Controller  类名上方  声明此类是一个SpringMVC Controller 对象,处理http请求  @RequestMapping  类或方 ...

  7. spring boot 学习(十二)拦截器实现IP黑名单

    拦截器实现IP黑名单 前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习.所以今天就将上次的”?秒防刷新”进行了一番修改.上次是采用注解加拦 ...

  8. Spring Boot(十四)RabbitMQ延迟队列

    一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...

  9. Spring Boot学习总结四

    利用阿里的druid来管理数据库连接池,在此数据上针对多数据源的情况,做下讲解.首先加上该包 <dependency> <groupId>com.alibaba</gro ...

随机推荐

  1. 对于“机器视觉(computer version)”的反思

    做图像有一段时间了,几个问题进行反思,欢迎讨论 1.机器视觉的本质是什么? 我认为就是通过计算机和数学的方法,对一定形式存储的2d或3d的视觉信号进行增强.延伸,以增加信号的强度: 2.机器视觉的第一 ...

  2. 20165310 Java实验五《网络编程与安全》

    20165310 Java实验五<网络编程与安全> 任务一 题目:①编写MyBC.java实现中缀表达式转后缀表达式的功能:②编写MyDC.java实现从上面功能中获取的表达式中实现后缀表 ...

  3. 2018-2019-1 1723《程序设计与数据结构》第1&2周作业 总结

    作业地址 第一周作业: https://edu.cnblogs.com/campus/besti/CS-IMIS-1723-2/homework/2092 提交情况如图: 第二周作业: https:/ ...

  4. BZOJ 2594 水管局长数据加强版(动态树)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2594 题意:给出一个无向图,边有权值.定义一条路径的长度为该路径所有边的最大值.两种操作 ...

  5. RSA加密解密中pkcs1与pkcs8格式私钥互相转换

    net,ios中rsa加解密使用的是pkcs1,而java使用的是pkcs8 如果是按1024取模(通常都是1024),pkcs1格式的私钥长度应该是812.如果是pkcs8的格式的密钥长度为861. ...

  6. 论文笔记:Mastering the game of Go with deep neural networks and tree search

    Mastering the game of Go with deep neural networks and tree search Nature 2015  这是本人论文笔记系列第二篇 Nature ...

  7. [Redis] - redis实战

    Microsoft Windows [版本 10.0.17134.472] (c) Microsoft Corporation.保留所有权利. C:\Users\SeeClanUkyo>f: F ...

  8. HBase底层存储原理——我靠,和cassandra本质上没有区别啊!都是kv 列存储,只是一个是p2p另一个是集中式而已!

    理解HBase(一个开源的Google的BigTable实际应用)最大的困难是HBase的数据结构概念究竟是什么?首先HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库.另一个不 ...

  9. 【TCP/IP协议 卷一:协议】第三章 IP:网际协议

    3.1 引言 unreliable不可靠的意思是它并不能保证IP数据报能成功的到达目的地.IP只提供尽力而为的传输服务. conectionless无连接的意思是IP并不维护任何关于后续数据报的状态信 ...

  10. UVa 1663 净化器

    https://vjudge.net/problem/UVA-1663 题意: 给m个长度为n的模板串,每个模板串包含字符0,1和最多一个星号"*",其中星号可以匹配0或1.例如, ...