一、安装Redis
- Windowss电脑可以从github.com/ServiceStac… 下载兼容Windows系统的redis
- 下载后解压,cd到对应目录执行
redis-server.exe redis.windows.conf
即可启动redis - 也可以直接到对应目录下双击执行
redis-server.exe
二、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
三、添加配置
spring:
redis:
# Redis服务器地址
host: 127.0.0.1
# Redis服务器端口号
port: 6379
# 使用的数据库索引,默认是0
database: 0
# 连接超时时间(毫秒)30*60*1000=30分钟=1800000
timeout: 1800000
lettuce:
pool:
# 最大阻塞等待时间,负数表示没有限制
max-wait: -1
# 连接池中的最大空闲连接
max-idle: 5
# 连接池中的最小空闲连接
min-idle: 0
# 连接池中最大连接数,负数表示没有限制
max-active: 20
四、添加配置类
- 设置使用json序列化对象和hash的key、value
- 不序列话final字段
- 设置日期json转换方式
objectMapper.registerModule(new JavaTimeModule())
- 设置仅序列化非空字段
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL)
,节省存储空间
package com.example.demo.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
@Configuration
public class RedisConfig {
/**
* retemplate相关配置
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
// 使用 JSON 序列化方式
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//不序列化final字段
objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
//解决LocalDateTime的转换问题
objectMapper.registerModule(new JavaTimeModule());
//仅序列化非空字段
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置 key 和 value 的序列化方式
template.setKeySerializer(jackson2JsonRedisSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
// 设置 hash key 和 hash value 的序列化方式
template.setHashKeySerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
五、封装redis操作常用方法
- 封装get、set(含设置超时时间)、del方法
package com.example.demo.service;
public interface RedisService {
Object get(String key);
boolean set(String key, Object value);
/**
*
* @param key
* @param value
* @param seconds 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return
*/
boolean set(String key, Object value, long seconds);
void del(String... keys);
}
package com.example.demo.service.impl;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.example.demo.service.RedisService;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* @author chenzl105
*/
@Service
public class RedisServiceImpl implements RedisService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
/**
* 普通缓存获取
*
* @param key 键
* @return 值
*/
@Override
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key 键
* @param value 值
* @return true成功 false失败
*/
@Override
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key 键
* @param value 值
* @param seconds 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
@Override
public boolean set(String key, Object value, long seconds) {
try {
if (seconds > 0) {
redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param keys 可以传一个值 或多个
*/
@Override
public void del(String... keys) {
if (ObjectUtils.isNotEmpty(keys)) {
if (keys.length == 1) {
redisTemplate.delete(keys[0]);
} else {
redisTemplate.delete(Arrays.asList(keys));
}
}
}
}
六、功能验证
- getById方法默认从redis获取缓存,获取不到再从数据库读取
- 读取完成后,把缓存更新到redis中
@Resource
private RedisService redisService;
//...
//省略部分代码
//...
@PostMapping("/getById")
@ApiOperation(value = "根据id查询系统用户表")
@ApiImplicitParams(
@ApiImplicitParam(name = "id", value = "主键id", required = true, dataType = "String")
)
public RestResult<UserInfoDetailResp> getById(String id) {
UserInfo userInfo = (UserInfo) redisService.get("userInfo:" + id);
if (null == userInfo) {
userInfo = userInfoService.getById(Long.parseLong(id));
}
if (null == userInfo) {
throw new BusinessException("id不存在");
}
redisService.set("userInfo:" + id, userInfo,10);
UserInfoDetailResp resp = UserInfoConverter.INSTANCE.convert2DetailResp(userInfo);
return RestResult.getSuccessResult(resp);
}
- UserInfo类的创建和更新时间,设置一下转json的格式为
yyyy-MM-dd HH:mm:ss
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@ApiModelProperty("创建时间")
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@ApiModelProperty("创建人")
@TableField(fill = FieldFill.INSERT)
private String createdBy;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@ApiModelProperty("最后修改时间")
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
- Redis中存储的内容如下
[
"com.example.demo.model.UserInfo",
{
"id": 2,
"userName": "2",
"vip": false,
"deleteFlag": 0,
"createTime": "2023-10-10 14:49:57",
"createdBy": "",
"updateTime": "2023-10-10 14:49:57",
"updatedBy": "",
"version": 0
}
]
- 测试可以发现,当redis中没有缓存时,会查询数据库,并且序列化到Redis中
- 10s内再次请求此接口,直接从Redis读取,不再查询数据库(没有打印SQL)
- 相同ID,10s内没有再次请求时,redis中缓存会自动删除
七、项目地址
PS:可以通过tag下载本文对应的代码版本
八、结尾
集成Redis已完成,有问题可以联系chenzhenlindx@qq.com