redis在springboot中使用
- 添加坐标
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 使用你的Jackson版本,处理时间格式不正确的问题 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.12.3</version>
</dependency>
- 添加配置文件
package com.sky.config;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sky.json.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.StringUtils;
import java.time.Duration;
/**
* Redis配置类,用于设置RedisTemplate的自定义序列化器。
* 此配置确保Java对象(包括Java 8日期/时间类型)在存储到Redis时能够正确序列化和反序列化。
*/
@Configuration
@Slf4j
public class RedisConfiguration extends CachingConfigurerSupport {
/**
* 定义一个RedisTemplate Bean,具有自定义的key和value序列化器。
* RedisTemplate配置为使用处理Java 8日期/时间类型的自定义Jackson ObjectMapper。
*
* @param redisConnectionFactory 用于创建Redis连接的工厂
* @return 配置好的RedisTemplate实例
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
log.info("redis配置类加载成功"); // 记录Redis配置类加载成功的信息
// 创建一个新的RedisTemplate实例
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
// 设置Redis连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用自定义的Jackson ObjectMapper处理Java 8日期/时间类型
ObjectMapper objectMapper = new JacksonObjectMapper();
// 设置序列化时包含类信息,保证反序列化时jackjson可以把数据转换成正确的对象
objectMapper.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
// 配置RedisTemplate的value序列化器,使用自定义的ObjectMapper
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
serializer.setObjectMapper(objectMapper);
// 设置RedisTemplate的key序列化器为StringRedisSerializer,将key序列化为字符串
// 设置RedisTemplate的value序列化器为Jackson2JsonRedisSerializer,将value序列化为JSON字符串
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(serializer);
// 设置RedisTemplate的hash key序列化器为StringRedisSerializer,将hash key序列化为字符串
// 设置RedisTemplate的hash value序列化器为Jackson2JsonRedisSerializer,将hash value序列化为JSON字符串
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(serializer);
// 返回配置好的RedisTemplate实例
return redisTemplate;
}
/**
* 配置RedisCacheManager,使用自定义的RedisCacheConfiguration。
* 处理springcache存储到Redis时的序列化问题
* @param redisConnectionFactory 用于创建Redis连接的工厂
* @return 配置好的RedisCacheManager实例
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 使用自定义的Jackson ObjectMapper处理Java 8日期/时间类型
ObjectMapper objectMapper = new JacksonObjectMapper();
// 设置序列化时包含类信息,保证反序列化时jackjson可以把数据转换成正确的对象
objectMapper.activateDefaultTyping(
objectMapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
// 配置缓存序列化器,使用自定义的Jackson2JsonRedisSerializer
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
serializer.setObjectMapper(objectMapper);
// 创建默认的缓存配置
RedisCacheConfiguration cacheConfig = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ZERO) // 设置缓存的默认过期时间,这里设置为1小时,设置为永久不过期:Duration.ZERO
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))//设置缓存键的序列化器。
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(serializer));//设置缓存值的序列化器。
// 返回配置好的RedisCacheManager实例
return RedisCacheManager.builder(redisConnectionFactory)
.cacheDefaults(cacheConfig)
.build();
}
/**
* 自定义缓存键生成策略
* @return KeyGenerator
*/
@Bean("customKeyGenerator")
@Override
public KeyGenerator keyGenerator() {
log.info("自定义缓存键生成策略");
return (target, method, params) -> {
StringBuilder resultStringBuilder = new StringBuilder("cache:");
resultStringBuilder.append(target.getClass().getSimpleName()).append(".");
resultStringBuilder.append(method.getName()).append(":");
StringBuilder paramStringBuilder = new StringBuilder();
for (Object param : params) {
if (param == null) {
paramStringBuilder.append("null,");
} else {
paramStringBuilder.append(param.toString()).append(",");
}
}
if (paramStringBuilder.length() > 0) {
paramStringBuilder.setLength(paramStringBuilder.length() - 1);
}
resultStringBuilder.append(paramStringBuilder);
log.info("自定义缓存键: {}", resultStringBuilder.toString());
return resultStringBuilder.toString();
};
}
}
- 时间转换器
package com.sky.config;
import com.sky.interceptor.JwtTokenAdminInterceptor;
import com.sky.interceptor.JwtTokenUserInterceptor;
import com.sky.json.JacksonObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.List;
/**
* 配置类,注册web层相关组件
*/
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
* 扩展MVC框架消息转换器
*
* @param converters 消息转换器列表
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转换器...");
// 创建一个消息转换器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
//设置对象转换器,可以将java对象转换为json字符串
converter.setObjectMapper(new JacksonObjectMapper());
//将外卖自己定义的转换器添加到spring MVC框架的消息转换器列表中,并且放在第一个位置
converters.add(0, converter);
}
}
- JacksonObjectMapper实现
package com.sky.json;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class JacksonObjectMapper extends ObjectMapper {
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
// 收到未知属性时不报异常
this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 反序列化时,属性不存在的兼容处理
this.getDeserializationConfig().without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 添加自定义序列化和反序列化器
SimpleModule simpleModule = new SimpleModule()
.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
// 注册功能模块,可以添加自定义序列化器和反序列化器
this.registerModule(simpleModule);
}
}
- 配置数据库
spring:
main:
allow-circular-references: true
redis:
host: localhost
port: 6379
password: 123456
database: 0
自定义键值对的使用示例:根据查询条件生成键值
/**
* 分页查询菜品
*
* @param dishPageQueryDTO 查询条件
* @return 菜品列表
*/
@GetMapping("/page")
@Cacheable(cacheNames = "dishCache", keyGenerator = "customKeyGenerator")
public Result getDishesByPage(DishPageQueryDTO dishPageQueryDTO) {
log.info("菜品分页查询:{}", dishPageQueryDTO);
PageResult dishesByPage = dishService.getDishesByPage(dishPageQueryDTO);
return Result.success(dishesByPage);
}
tor")
public Result getDishesByPage(DishPageQueryDTO dishPageQueryDTO) {
log.info(“菜品分页查询:{}”, dishPageQueryDTO);
PageResult dishesByPage = dishService.getDishesByPage(dishPageQueryDTO);
return Result.success(dishesByPage);
}
[外链图片转存中...(img-LCVIAb2H-1723969758036)]