spring boot redis 缓存(cache)集成
Spring Boot 集成教程
- Spring Boot 介绍
- Spring Boot 开发环境搭建(Eclipse)
- Spring Boot Hello World (restful接口)例子
- spring boot 连接Mysql
- spring boot配置druid连接池连接mysql
- spring boot集成mybatis(1)
- spring boot集成mybatis(2) – 使用pagehelper实现分页
- spring boot集成mybatis(3) – mybatis generator 配置
- spring boot 接口返回值封装
- spring boot输入数据校验(validation)
- spring boot rest 接口集成 spring security(1) – 最简配置
- spring boot rest 接口集成 spring security(2) – JWT配置
- spring boot 异常(exception)处理
- spring boot 环境配置(profile)切换
- spring boot redis 缓存(cache)集成
概述
本文介绍spring boot项目集成redis缓存的过程。
redis是一个开源的内存NOSQL数据库,在web开发中主要被用于数据缓存。一般在高并发的情况下,web服务器接受访问时,直接从数据库加载是慢的,需要把常用数据缓存到redis中,提高加载速度和并发能力。
项目内容
创建一个spring boot项目,配置redis各相关 bean,实现几个接口,通过两种方式测试redis缓存:
- 以注解方式自动缓存
- RedisTemplate手动访问redis服务器
要求
如没有开发环境,可参考前面章节:[spring boot 开发环境搭建(Eclipse)]。
项目创建
创建spring boot项目
打开Eclipse,创建spring boot的spring starter project项目,选择菜单:File > New > Project ...,弹出对话框,选择:Spring Boot > Spring Starter Project,在配置依赖时,勾选web、redis,完成项目创建。

项目依赖
需要用到commons-pool2库,在pom.xml中添加依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
项目配置
在application.properties文件中配置redis服务器的连接
## REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=192.168.0.99
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.lettuce.pool.min-idle=0
代码实现
项目目录结构如下图,我们添加了几个类,下面将详细介绍。

Redis Java配置(RedisConfig.java)
首先使用@EnableCaching开启以注解方式使用缓存。
然后配置redis相关的bean
- RedisTemplate - 访问redis的bean,用于手动访问redis服务器
- 缓存管理器 - 注解方式使用缓存的配置
- KeyGenerator - 自定义缓存key的生成
- Json序列化 - Json对象被缓存时的序列化
/**
* @description redis配置 配置序列化方式以及缓存管理器
*/
@EnableCaching // 开启缓存
@Configuration
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {
/**
* 配置自定义redisTemplate
*
* @param connectionFactory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setValueSerializer(jackson2JsonRedisSerializer());
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
/**
* json序列化
* @return
*/
@Bean
public RedisSerializer<Object> jackson2JsonRedisSerializer() {
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
serializer.setObjectMapper(mapper);
return serializer;
}
/**
* 配置缓存管理器
* @param redisConnectionFactory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 生成一个默认配置,通过config对象即可对缓存进行自定义配置
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
// 设置缓存的默认过期时间,也是使用Duration设置
config = config.entryTtl(Duration.ofMinutes(1))
// 设置 key为string序列化
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
// 设置value为json序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
// 不缓存空值
.disableCachingNullValues();
// 设置一个初始化的缓存空间set集合
Set<String> cacheNames = new HashSet<>();
cacheNames.add("timeGroup");
cacheNames.add("user");
// 对每个缓存空间应用不同的配置
Map<String, RedisCacheConfiguration> configMap = new HashMap<>();
configMap.put("timeGroup", config);
configMap.put("user", config.entryTtl(Duration.ofSeconds(120)));
// 使用自定义的缓存配置初始化一个cacheManager
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory)
// 一定要先调用该方法设置初始化的缓存名,再初始化相关的配置
.initialCacheNames(cacheNames)
.withInitialCacheConfigurations(configMap)
.build();
return cacheManager;
}
/**
* 缓存的key是 包名+方法名+参数列表
*/
@Bean
public KeyGenerator keyGenerator() {
return (target, method, objects) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append("::" + method.getName() + ":");
for (Object obj : objects) {
sb.append(obj.toString());
}
return sb.toString();
};
}
}
添加实体类 User
public class User {
private long id;
private String nickname;
private String mobile;
@JsonProperty(access = Access.WRITE_ONLY) //在输出的Json数据中隐藏密码,只能输入不输出
private String password;
private String role;
public User(long id, String nickname, String mobile, String password, String role) {
this.id = id;
this.nickname = nickname;
this.mobile = mobile;
this.password = password;
this.role = role;
}
public User() {
super();
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
常用的缓存注解
@Cacheable- 表明对应方法的返回结果可以被缓存,首次调用后,下次就从缓存中读取结果,方法不会再被执行了。@CachePut- 更新缓存,方法每次都会执行@CacheEvict- 清除缓存,方法每次都会执行
添加User的服务层
因为主要的业务逻辑在服务层实现,一般会把缓存注解加在服务层的方法上。
下面几个服务层的方法会加缓存注解:
- getUserById - 方法的返回结果会被缓存到redis,使用注解
@Cacheable - updateUserNickname - 原始数据被更新了,废弃缓存数据,使用注解
@CacheEvict
UserSevice.java 接口
public interface UserService {
public User getUserById(long userId);
public User updateUserNickname(long userId, String nickname);
}
UserServiceImpl.java 实现类
@Service("userService")
public class UserServiceImpl implements UserService {
private static final org.slf4j.Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
private User user = new User(1l, "abc1", "13512345678", "123456", "role-user");
@Cacheable(value = "user", key= "#userId")
@Override
public User getUserById(long userId) {
log.info("加载用户信息");
return user;
}
@CacheEvict(value = "user", key= "#userId")
@Override
public User updateUserNickname(long userId, String nickname) {
user.setNickname(nickname);
return user;
}
}
添加User的控制层
@RestController
@EnableAutoConfiguration
@RequestMapping("/user")
public class UserController {
// 注入service类
@Resource
private UserService userService;
// 注入RedisTemplate
@Resource
private RedisTemplate<String, Object> redis;
// 读取用户信息,测试缓存使用:除了首次读取,接下来都应该从缓存中读取
@RequestMapping(value="{id}", method=RequestMethod.GET, produces="application/json")
public User getUser(@PathVariable long id) throws Exception {
User user = this.userService.getUserById(id);
return user;
}
// 修改用户信息,测试删除缓存
@RequestMapping(value = "/{id}/change-nick", method = RequestMethod.POST, produces="application/json")
public User changeNickname(@PathVariable long id) throws Exception{
String nick = "abc-" + Math.random();
User user = this.userService.updateUserNickname(id, nick);
return user;
}
// 使用RedisTemplate访问redis服务器
@RequestMapping(value="/redis", method=RequestMethod.GET, produces="application/json")
public String redis() throws Exception {
// 设置键"project-name",值"qikegu-springboot-redis-demo"
redis.opsForValue().set("project-name", "qikegu-springboot-redis-demo");
String value = (String) redis.opsForValue().get("project-name");
return value;
}
}
运行
Eclipse左侧,在项目根目录上点击鼠标右键弹出菜单,选择:run as -> spring boot app 运行程序。 打开Postman访问接口,
同时监控redis服务器。
监控redis服务器,使用
redis-cli命令连上服务器,然后使用monitor命令开始监控:
运行结果如下:
获取用户信息

redis中的数据,可以看到数据通过SET指令保存进redis了

多次获取用户信息,可以看到通过GET指令从redis中读取缓存

修改用户信息

redis中的缓存被删除了

测试使用RedisTemplate访问redis服务器

redis中的数据变化

总结
spring boot redis 缓存(cache)集成的更多相关文章
- spring boot redis缓存JedisPool使用
spring boot redis缓存JedisPool使用 添加依赖pom.xml中添加如下依赖 <!-- Spring Boot Redis --> <dependency> ...
- spring boot redis缓存入门
摘要: 原创出处 泥瓦匠BYSocket 下载工程 springboot-learning-example ,工程代码注解很详细.JeffLi1993/springboot-learning-exam ...
- Spring Boot Redis 集成配置(转)
Spring Boot Redis 集成配置 .embody{ padding:10px 10px 10px; margin:0 -20px; border-bottom:solid 1px #ede ...
- Spring Boot 项目学习 (三) Spring Boot + Redis 搭建
0 引言 本文主要介绍 Spring Boot 中 Redis 的配置和基本使用. 1 配置 Redis 1. 修改pom.xml,添加Redis依赖 <!-- Spring Boot Redi ...
- 使用maven简单搭建Spring mvc + redis缓存
注:此文参考并整合了网上的文章 <spring缓存机制>:http://blog.csdn.net/sidongxue2/article/details/30516141 <配置 S ...
- Spring Boot微服务如何集成fescar解决分布式事务问题?
什么是fescar? 关于fescar的详细介绍,请参阅fescar wiki. 传统的2PC提交协议,会持有一个全局性的锁,所有局部事务预提交成功后一起提交,或有一个局部事务预提交失败后一起回滚,最 ...
- spring boot + redis 实现session共享
这次带来的是spring boot + redis 实现session共享的教程. 在spring boot的文档中,告诉我们添加@EnableRedisHttpSession来开启spring se ...
- Spring Boot 2.0 快速集成整合消息中间件 Kafka
欢迎关注个人微信公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site ...
- Spring Boot与ActiveMQ的集成
Spring Boot对JMS(Java Message Service,Java消息服务)也提供了自动配置的支持,其主要支持的JMS实现有ActiveMQ.Artemis等.本节中,将以Active ...
随机推荐
- 020、MySQL创建一个存储过程,显示存储过程,调用存储过程,删除存储过程
一.我们创建一个MySQL储存过程,在SQL代码区写入以下内容,并执行就可以了 #编写一个存储过程 CREATE PROCEDURE ShowDate ( ) BEGIN #输出当前时间 SELECT ...
- Hive 中的 order by, sort by, distribute by 与 cluster by
Order By order by 会对输入做全排序, 因此只有一个Reducer(多个Reducer无法保证全局有序), 然而只有一个Reducer, 会导致当输入规模较大时, 消耗较长的计算时间. ...
- Django(十一)视图详解:基本使用、登录实例、HttpReqeust对象、HttpResponse对象
一.视图(基于类的视图) [参考]https://docs.djangoproject.com/zh-hans/3.0/topics/class-based-views/intro/ 1)视图的功能 ...
- 十五、React:简单点餐实例:知识点,html解析写法
一.功能 从首页列表点进去,转到详情页 列表.详情从Api获取 Api列表:http://a.itying.com/api/productlist 详情:http://a.itying.com/api ...
- ACM-最优配餐
题目描述: 最优配餐 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 栋栋最近开了一家餐饮连锁店,提供外卖服务.随着连锁店越来越多,怎么合理的给客户送餐成为了一个急需解决的问 ...
- JuJu团队11月27号工作汇报
JuJu团队11月27号工作汇报 JuJu Scrum 团队成员 今日工作 剩余任务 困难 于达 将真实数据处理后按矩阵读入, 以供训练使用 提供generator的接口 对julia语言还不够 ...
- POJ 3983:快算24
快算24 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4791 Accepted: 2930 Description ...
- lvm 通过扩容本身磁盘容量扩容
场景:sdb之前是3G容量,现在扩容了sdb的容量到8G.现在把新扩容的5G容量扩展到现有的逻辑卷中 [root@localhost ~]# pvresize /dev/sdb Physical v ...
- 根据上传的MultipartFile通过springboot转化为File类型并调用通过File文件流的方法上传特定服务器
@PostMapping("uploadExcel") public ResponseObj uploadExcel(@RequestParam("excelFile ...
- 微服务框架中springboot启动的一个问题
微服务中,采用的是springboot构建单个项目,其中一个项目user启动过程中总是启动补起来,相关的地方都没有错,始终启动不起来,而且要命的是控制台不打印日志,日志级别是debug级别的,但是打印 ...
