Springboot集成Redis缓存
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
Redis是一个开源的使用ANSI C语言编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。
选择了集中式缓存,在 SpringBoot 工程中使用 Redis 进行缓存。
所需要的依赖:
里面有web依赖,mybatis,mysql数据库连接,spring boot redis 依赖,缓存依赖,还有简化代码的lombok,阿里的fastjson
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.41</version>
</dependency>
<!-- 缓存依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.31</version>
</dependency>
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
还需要写个redis的配置类
@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(1000); //设置 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);
}
}
redisConnectionFactory()
方法是用来创建redis服务器的连接
cacheManager.setDefaultExpiration()
是用来设置redis缓存数据过期的时间,单位是s(秒)
1创建实体类
使用lombok
方便我们去创建实体类,不需要再写set和get方法
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String id;
private String name;
private Integer age;
}
2.mapper接口
有最基本的增删改查
@Component
public interface UserMapper {
void delete(String id);
void update(User user);
User findById(String id);
void save(User user) ;
}
3.对应的mapper的xml文件
<selectKey resultType="string" keyProperty="id" order="BEFORE">SELECT UUID()</selectKey>
是用来生成唯一的id
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.pjb.mapper.UserMapper">
<!--映射实体对象-->
<resultMap id="UserResultMap" type="com.pjb.model.User" autoMapping="true">
<id property="id" column="id" />
</resultMap>
<insert id="save">
<selectKey resultType="string" keyProperty="id" order="BEFORE">SELECT UUID()</selectKey>
INSERT INTO rusers(id,`name`, age)
VALUES (#{id},#{name}, #{age})
</insert>
<select id="findById" resultMap="UserResultMap">
SELECT * FROM rusers WHERE id = #{id}
</select>
<delete id="delete">
DELETE FROM rusers WHERE id = #{id}
</delete>
<update id="update">
UPDATE rusers
SET name=#{name}, age=#{age}
WHERE id=#{id}
</update>
</mapper>
4.service部分
@CacheConfig(cacheNames = "users")
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@CachePut(key = "'user_'+#user.getId()")
public User save(User user) {
userMapper.save(user);
return userMapper.findById(user.getId());
}
@CachePut(key = "'user_'+#user.getId()")
public User update(User user) {
userMapper.update(user);
return userMapper.findById(user.getId());
}
@Cacheable(key="'user_'+#id")
public User findById(String id){
System.err.println("没有走缓存!"+id);
return userMapper.findById(id);
}
@CacheEvict(key = "'user_'+#id")//这是清除缓存
public void delete(String id){
userMapper.delete(id);
}
}
关于 SpringBoot 缓存注解
@EnableCaching
: 开启SpringBoot缓存策略,放在启动主类。
@CacheConfig(cacheNames = "XXX")
: 设置一个名为”XXX”的缓存空间。
@Cacheable
: Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。多用于查操作
@CacheEvict
: 清除缓存。多用于删除操作
@CachePut
: 也可以声明一个方法支持缓存功能。使用@CachePut
标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。多用于增和改操作
5.controller
@RestController
public class UserController {
@Autowired
private UserService userService;
@PostMapping("/user")
public Object addUser (@RequestBody User user){
Object data=userService.save(user);
JSONObject jsonObject=new JSONObject();
jsonObject.put("message",data);
return jsonObject;
}
@GetMapping("/user/{id}")
public Object findUser(@PathVariable String id){
JSONObject jsonObject=new JSONObject();
jsonObject.put("message",userService.findById(id));
return jsonObject;
}
@PutMapping("/user")
public Object updateUser(@RequestBody User user){
JSONObject jsonObject=new JSONObject();
if(userService.findById(user.getId())!=null){
jsonObject.put("message",userService.update(user));
return jsonObject;
}
jsonObject.put("message","用户不存在");
return jsonObject;
}
@DeleteMapping("/user/{id}")
public Object deleteUser(@PathVariable String id){
JSONObject jsonObject=new JSONObject();
if(userService.findById(id)!=null){
userService.delete(id);
jsonObject.put("message","删除成功");
return jsonObject;
}
jsonObject.put("message","用户不存在");
return jsonObject;
}
}
6.用postman
测试,验证redis的缓存
添加用户
Paste_Image.png用
redis desktop manager
看下缓存数据Paste_Image.png
数据已经存在redis中了
查询用户
Paste_Image.png在这里可能看不出缓存的存在
但是你在控制台发现并没有文字输出,证明数据是从缓存中取的
Paste_Image.png
修改用户
Paste_Image.png来看看缓存,先刷新下缓存,缓存数据更新了,说明
@CachePut
的确有用Paste_Image.png
删除用户
Paste_Image.png然后刷新下缓存,数据已经找不到了
Paste_Image.png
用
redis desktop manager
刷新缓存的操作Paste_Image.png
其实要注意的是增删改查的key值要相同,不然对应的value是操作不了的
就好像删除的key写成
key = "'user_'+#uuid"
这样是删不了redis的数据的,只要redis有需要的数据,服务就不会进入数据库