redis在springboot中使用

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);
}

image-20240713004156426
tor")
public Result getDishesByPage(DishPageQueryDTO dishPageQueryDTO) {
log.info(“菜品分页查询:{}”, dishPageQueryDTO);
PageResult dishesByPage = dishService.getDishesByPage(dishPageQueryDTO);
return Result.success(dishesByPage);
}


[外链图片转存中...(img-LCVIAb2H-1723969758036)]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值