spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战
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缓存支持。
<!-- 缓存依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- spring boot redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
3. application.properties 配置
有关于 Redis 配置参数:
# Redis 配置(默认配置)
# Redis 数据库索引(默认为0)
spring.redis.database=0
# Redis 服务器地址
spring.redis.host=localhost
# Redis 服务器端口
spring.redis.port=6379
# Redis 服务器密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 设置连接超时
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 并没有帮我们封装好(或者我没有找到)。
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport { @Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private int timeout; @Bean
public KeyGenerator wiselyKeyGenerator(){
return new KeyGenerator() {
@Override
public Object generate(Object o, Method method, Object... objects) {
StringBuilder sb = new StringBuilder();
sb.append(o.getClass().getName());
sb.append(method.getName());
for (Object obj : objects){
sb.append(obj.toString());
}
return sb.toString();
}
};
} @Bean
public JedisConnectionFactory redisConnectionFactory(){
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setTimeout(timeout); //设置连接超时
return factory;
} @Bean
public CacheManager cacheManager(RedisTemplate redisTemplate){
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
cacheManager.setDefaultExpiration(10); //设置 key-value 超时时间
return cacheManager;
} @Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
StringRedisTemplate template = new StringRedisTemplate(factory);
setSerializer(template); //设置序列化工具,就不必实现Serializable接口
template.afterPropertiesSet();
return template;
} private void setSerializer(StringRedisTemplate template){
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
}
}
其它
其他代码就不累赘贴出来了,直接参考一下我的Github仓库 : https://github.com/FunriLy/springboot-study/tree/master/%E6%A1%88%E4%BE%8B10
启动工程后,访问 http://localhost:8080/redis ,我们可以在控制台看到以下结果:
没有走缓存!8b10aba26bd5402bbdad2584d8452f1f
User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='张三', age=20}
User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='张三', age=20}
====== 修改 Redis 缓存数据 ======
User{uuid='8b10aba26bd5402bbdad2584d8452f1f', name='李四', age=18}
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 配置类
@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 86400*30)
public class HttpSessionConfig {
// 默认无配置
}
2. 添加验证的URL接口
@Value("${server.port}")
String port;
@RequestMapping(value = "/session", method = RequestMethod.GET)
public Object getSession(HttpServletRequest request){
Map<String, Object> map = new HashMap<String, Object>();
map.put("SessionId", request.getSession().getId());
map.put("ServerPort", "服务端口号为 "+port);
return map;
}
同时启动两个相同的工程(比如:8080端口与9090端口),访问 http://localhost:8080/session 与 http://localhost:9090/session
我们可以得到以下结果:
{"SessionId":"01f353e1-5cd3-4fbd-a5d0-9a73e17dcec2","ServerPort":"服务端口号为 8080"}
{"SessionId":"01f353e1-5cd3-4fbd-a5d0-9a73e17dcec2","ServerPort":"服务端口号为 9090"}
结果中的SessionId是一致的,却是由两个不同项目工程来提供服务。这样子,SpringSession 利用拦截器 Filter 帮我们在每个请求前进行了同步设置,达到了分布式系统中 session 共享。
spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战的更多相关文章
- spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法
spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法 前言 本篇接着<spring boot / cloud ...
- spring boot 学习(十)SpringBoot配置发送Email
SpringBoot配置发送Email 引入依赖 在 pom.xml 文件中引入邮件配置: <dependency> <groupId>org.springframework. ...
- Spring Boot (十四): 响应式编程以及 Spring Boot Webflux 快速入门
1. 什么是响应式编程 在计算机中,响应式编程或反应式编程(英语:Reactive programming)是一种面向数据流和变化传播的编程范式.这意味着可以在编程语言中很方便地表达静态或动态的数据流 ...
- spring boot 学习10 定义springboot的两种方法
使用spring boot的两种方法: A:继承spring-boot-starter-parent项目 这种方式很简单,只需要在POM里面添加parent父工程即可. B: 如果你不喜欢继承spri ...
- spring Boot 学习(四、Spring Boot与任务)
一.异步任务 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在 处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用 多线程来完成此类任务,其实,在Spri ...
- Spring Boot学习(四)常用注解
一.注解对照表 注解 使用位置 作用 @Controller 类名上方 声明此类是一个SpringMVC Controller 对象,处理http请求 @RequestMapping 类或方 ...
- spring boot 学习(十二)拦截器实现IP黑名单
拦截器实现IP黑名单 前言 最近一直在搞 Hexo+GithubPage 搭建个人博客,所以没怎么进行 SpringBoot 的学习.所以今天就将上次的”?秒防刷新”进行了一番修改.上次是采用注解加拦 ...
- Spring Boot(十四)RabbitMQ延迟队列
一.前言 延迟队列的使用场景:1.未按时支付的订单,30分钟过期之后取消订单:2.给活跃度比较低的用户间隔N天之后推送消息,提高活跃度:3.过1分钟给新注册会员的用户,发送注册邮件等. 实现延迟队列的 ...
- Spring Boot学习总结四
利用阿里的druid来管理数据库连接池,在此数据上针对多数据源的情况,做下讲解.首先加上该包 <dependency> <groupId>com.alibaba</gro ...
随机推荐
- 20145307陈俊达_安卓逆向分析_Xposed的hook技术研究
20145307陈俊达_安卓逆向分析_Xposed的hook技术研究 引言 其实这份我早就想写了,xposed这个东西我在安卓SDK 4.4.4的时候就在玩了,root后安装架构,起初是为了实现一些屌 ...
- [c/c++]指针(3)
在指针2中提到了怎么用指针申配内存,但是,指针申配的内存不会无缘无故地 被收回.很多poj上的题都是有多组数据,每次地数组大小会不同,所以要重新申请 一块内存.但是原来的内存却不会被收回,也是说2.3 ...
- libcurl开源库在Win32程序中使用下载文件显示进度条实例
一.配置工程引用libcurl库 #define CURL_STATICLIB #include "curl/curl.h" #ifdef _DEBUG #pragma comme ...
- JQuery插件模板
(function($){ $.fn.插件名 = function(settings){ var defaultSettings = { } /* 合并默认参数和用户自定义参数 */settings ...
- 如果恨一个程序员,忽悠他去做iOS开发
如果你恨一个程序员,忽悠他去做iOS开发.不管他背景是cobel还是 java,送他一本iOS开发的书.这种书最好是国人写的,容易以偏概全一点,相比洋鬼子的书,更容易学到皮毛.这叫舍不得孩子套不着狼, ...
- JavaScript callee caller
caller是function的属性 callee是arguments的属性 callee:返回正在执行的函数对象. var sum = function (n) { == n) ; ); } con ...
- BZOJ5293: [Bjoi2018]求和 树上差分
Description master 对树上的求和非常感兴趣.他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k 次方和,而且每次的k 可能是不同的.此处节点深度的定义是这个节点 ...
- QQ名片自动点赞
2017-01-23 简介:QQ名片自动点赞,1秒左右可点完1屏好友的赞,每个好友10个赞. 尺寸: 720*1280 DPI:320 宿主:3.1.2.10711 系统:Android v5.11 ...
- Z-score(Z值)的意义--转载
http://blog.sina.com.cn/s/blog_72208a6a0101cdt1.html http://www.docin.com/p-350677620.html http://we ...
- Miller_Rabin(米勒拉宾)素数测试算法
首先需要知道两个定理: 1: 费马小定理: 假如p是素数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p). 2:二次探测定理:如果p是素数,x是小于p的正整数,且,那么要么x=1,要么x ...