最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Data Redis對象緩存序列化問題解決

 更新時間:2024年01月04日 10:07:43   作者:馮文議  
相信在項目中,你一定是經(jīng)常使用Redis,在使用時,有沒有遇到同我一樣,對象緩存序列化問題的呢,本文主要介紹了Spring Data Redis對象緩存序列化問題解決,感興趣的可以了解一下

相信在項目中,你一定是經(jīng)常使用 Redis ,那么,你是怎么使用的呢?在使用時,有沒有遇到同我一樣,對象緩存序列化問題的呢?那么,你又是如何解決的呢?

Redis 使用示例

添加依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

在應(yīng)用啟動如何添加啟用緩存注解(@EnableCaching)。

假如我們有一個用戶對象(UserVo):

@Data
public class UserVo implements Serializable {

    @Serial
    private static final long serialVersionUID = 2215423070276994378L;

    private Long id;

    private String name;

    private LocalDateTime createDateTime;

}

這里,我們實現(xiàn)了 Serializable 接口。

在我們需要緩存的方法上,使用 @Cacheable 注解,就表示如果返回的對象不是 null 時,就會對其進行緩存,下次查詢,首先會去緩存中查詢,查到了,就直接返回,不會再去數(shù)據(jù)庫查詢,查不到,再去數(shù)據(jù)庫查詢。

@Service
@Slf4j
public class UserServiceImpl implements IUserService {

    @Override
    @Cacheable(
            value = "sample-redis",
            key = "'user-'+#id",
            unless = "#result == null"
    )
    public UserVo getUserById(Long id) {

        log.info("userVo from db query");

        UserVo userVo = new UserVo();
        userVo.setId(1L);
        userVo.setName("Zhang San");
        userVo.setCreateDateTime(LocalDateTime.now());

        return userVo;
    }

}

核心代碼:

@Cacheable(
        value = "sample-redis",
        key = "'user-'+#id",
        unless = "#result == null"
)

模擬測試,再寫一個測試接口:

@RestController
@RequestMapping("/sample")
@RequiredArgsConstructor
@Slf4j
public class SampleController {

    private final IUserService userService;

    @GetMapping("/user/{id}")
    public UserVo getUserById(@PathVariable Long id) {

        UserVo vo = userService.getUserById(id);

        log.info("vo: {}", JacksonUtils.json(vo));

        return vo;
    }

}

我們再加上連接 redis 的配置:

spring:
  data:
    redis:
      host: localhost
      port: 6379

測試:

### getUserById
GET http://localhost:8080/sample/user/1

在這里插入圖片描述

輸出結(jié)果跟我們想的一樣,第一次從數(shù)據(jù)庫查,后面都從緩存直接返回。

總結(jié)一下:

  • 添加 spring-boot-starter-data-redis 依賴。

  • 使用啟用緩存注解(@EnableCaching)。

  • 需要緩存的對象實現(xiàn) Serializable 接口。

  • 使用 @Cacheable 注解緩存查詢的結(jié)果。

遇到問題

在上面我們通過 spring boot 提供的 redis 實現(xiàn)了查詢對象緩存這樣一個功能,有下面幾個問題:

  • 緩存的對象,必須序列化,不然會報錯。
  • redis 存儲的數(shù)據(jù),看不懂,可以轉(zhuǎn)成 json 格式嗎?
  • 使用 Jackson 時,遇到特殊類型的字段會報錯,比如 LocalDateTime。

第1個問題,如果對象沒有實現(xiàn) Serializable 接口,會報錯:

在這里插入圖片描述

關(guān)鍵信息:

java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [xxx.xxx.UserVo]

我詳細(xì)描述一下第3個問題,默認(rèn)是使用 Jdk序列化 JdkSerializationRedisSerializer,redis 里面存的數(shù)據(jù)如下:

在這里插入圖片描述

問題很明顯,對象必須要實現(xiàn)序列化接口,存的數(shù)據(jù)不易查看,所以,改用 GenericJackson2JsonRedisSerializer ,這就有了第3個問題。

我們加上下面的配置,就能解決第2個問題。

@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
    return RedisCacheConfiguration
            .defaultCacheConfig()
            .serializeValuesWith(
                    RedisSerializationContext
                            .SerializationPair
                            .fromSerializer(RedisSerializer.json())
            );
}

下面看第三個問題的錯誤:

在這里插入圖片描述

如何解決?

既然有了明確的錯誤提示,那也是好解決的,我們可以這樣:

@JsonDeserialize(using = LocalDateTimeDeserializer.class)		// 反序列化
@JsonSerialize(using = LocalDateTimeSerializer.class)		    // 序列化
private LocalDateTime createDateTime;

這樣就可以了,我們看下redis里面存的數(shù)據(jù):

{"@class":"com.fengwenyi.erwin.component.sample.redis.vo.UserVo","id":1,"name":"Zhang San","createDateTime":[2023,12,29,23,44,3,479011000]}

其實到這里,已經(jīng)解決了問題,那有沒有更省心的辦法呢?

解決辦法

其實我們知道,使用的就是 Jackson 進行 json 轉(zhuǎn)換,而 json 轉(zhuǎn)換,遇到 LocalDateTime 問題時,我們配置一下 module 就可以了,因為默認(rèn)用的 SimpleModule,我們改用 JavaTimeModule 就可以了。

這時候問題又來啦,錯誤如下:

在這里插入圖片描述

這時候存的數(shù)據(jù)如下:

{"id":1,"name":"Zhang San","createDateTime":"2023-12-29T23:31:52.548517"}

這就涉及到 Jackson 序列化漏洞的問題了,采用了白名單機制,我們就粗暴一點:

jsonMapper.activateDefaultTyping(
  LaissezFaireSubTypeValidator.instance, 
  ObjectMapper.DefaultTyping.NON_FINAL
);

redis 存的數(shù)據(jù)如下:

["com.fengwenyi.erwin.component.sample.redis.vo.UserVo",{"id":1,"name":"Zhang San","createDateTime":"2023-12-29T23:56:18.197203"}]

最后,來一段完整的 RedisCacheConfiguration 配置代碼:

@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
    return RedisCacheConfiguration
            .defaultCacheConfig()
            .serializeValuesWith(
                    RedisSerializationContext
                            .SerializationPair
//                            .fromSerializer(RedisSerializer.json())
//                            .fromSerializer(
//                                    new GenericJackson2JsonRedisSerializer()
//                            )
                            .fromSerializer(redisSerializer())
            );
}

private RedisSerializer<Object> redisSerializer() {
    JsonMapper jsonMapper = new JsonMapper();
    JacksonUtils.configure(jsonMapper);
    jsonMapper.activateDefaultTyping(
            LaissezFaireSubTypeValidator.instance, 
            ObjectMapper.DefaultTyping.NON_FINAL
    );
    return new GenericJackson2JsonRedisSerializer(jsonMapper);
}

到此這篇關(guān)于Spring Data Redis對象緩存序列化問題解決的文章就介紹到這了,更多相關(guān)Spring Data Redis對象緩存序列化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java?NIO實戰(zhàn)之多人聊天室

    Java?NIO實戰(zhàn)之多人聊天室

    這篇文章主要為大家詳細(xì)介紹了Java?NIO實戰(zhàn)之多人聊天室,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 詳解Java中JSON數(shù)據(jù)的生成與解析

    詳解Java中JSON數(shù)據(jù)的生成與解析

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Java中JSON數(shù)據(jù)的生成與解析展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Java中SimpleDateFormat方法超詳細(xì)分析

    Java中SimpleDateFormat方法超詳細(xì)分析

    這篇文章主要給大家介紹了關(guān)于Java中SimpleDateFormat方法超詳細(xì)分析的相關(guān)資料,SimpleDateFormat 是一個以國別敏感的方式格式化和分析數(shù)據(jù)的具體類,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-08-08
  • Java如何利用Socket傳輸信息或文件

    Java如何利用Socket傳輸信息或文件

    這篇文章主要介紹了Java如何利用Socket傳輸信息或文件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • 使用Jenkins配置Git+Maven的自動化構(gòu)建的方法

    使用Jenkins配置Git+Maven的自動化構(gòu)建的方法

    這篇文章主要介紹了使用Jenkins配置Git+Maven的自動化構(gòu)建的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • Java中的線程同步全面講解

    Java中的線程同步全面講解

    線程同步指的是在多線程環(huán)境下,通過某種機制來協(xié)調(diào)多個線程對共享資源的訪問,確保在同一時刻只有一個線程能夠訪問共享資源,從而避免數(shù)據(jù)不一致和其他并發(fā)問題,這篇文章主要介紹了Java中線程同步的相關(guān)資料,需要的朋友可以參考下
    2025-07-07
  • 詳解Spring中BeanUtils工具類的使用

    詳解Spring中BeanUtils工具類的使用

    這篇文章主要通過一些示例為大家詳細(xì)介紹了Spring中BeanUtils工具類的使用,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下
    2022-06-06
  • 詳解MyBatis自定義Plugin插件

    詳解MyBatis自定義Plugin插件

    這篇文章主要介紹了MyBatis自定義Plugin插件的相關(guān)知識,實現(xiàn)方法也很簡單,只需實現(xiàn) Interceptor 接口,并指定想要攔截的方法簽名即可,需要的朋友可以參考下
    2018-06-06
  • Java微服務(wù)無損發(fā)布生產(chǎn)實戰(zhàn)案例及驗證

    Java微服務(wù)無損發(fā)布生產(chǎn)實戰(zhàn)案例及驗證

    微服務(wù)架構(gòu)是一項在云中部署應(yīng)用和服務(wù)的新技術(shù),這篇文章主要介紹了Java微服務(wù)無損發(fā)布生產(chǎn)實戰(zhàn)及驗證的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-10-10
  • 一文帶你玩轉(zhuǎn)Java異常處理

    一文帶你玩轉(zhuǎn)Java異常處理

    這篇文章主要為大家介紹一下Java中的異常處理機制,文中通過示例為大家進行了詳細(xì)的介紹,對我們學(xué)習(xí)有一定的幫助,感興趣的可以了解一下
    2022-08-08

最新評論

沙河市| 罗定市| 本溪市| 济宁市| 汉沽区| 钦州市| 定结县| 石景山区| 杂多县| 青浦区| 太和县| 驻马店市| 盐亭县| 昔阳县| 奎屯市| 八宿县| 兴城市| 开阳县| 饶平县| 游戏| 临沂市| 贡山| 定结县| 长丰县| 栾川县| 米脂县| 双鸭山市| 梁平县| 达拉特旗| 资中县| 喜德县| 益阳市| 崇明县| 潢川县| 舟山市| 阳东县| 化德县| 扎赉特旗| 英吉沙县| 石城县| 丹阳市|