Spring Boot MyBatis 使用 Redis 做爲二級緩存遇到的問題

在 Spring Boot MyBatis使用 Redis 做爲二級緩存的時候,遇到了一個使人詭異的問題,在 MyBatis 從 Redis 中取出緩存並反序列的時候老是報這個錯誤java

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ClassCastException: hello.entity.User cannot be cast to hello.entity.User
java.lang.ClassCastException: hello.entity.User cannot be cast to hello.entity.User
....

根據異常能夠看出是類型不匹配的異常,可是一樣的類名,一樣的字段,怎麼就不匹配了呢?web

我首先 MyBatis Redis cache 庫是否是有BUG,已經它一直帶着個 beta 的字眼,並且已經4年沒更新了redis

<dependency>
            <groupId>org.mybatis.caches</groupId>
            <artifactId>mybatis-redis</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

可是我換成 MyBatis Memcache cache 用 Memcached 作二級緩存也是一樣的問題,感受應該不是 MyBatis 的問題了,spring

而後我轉換思路搜索 Spring Boot ClassCastException 終於找到了問題所在,原來是 spring-boot-devtools 的鍋緩存

https://stackoverflow.com/questions/37977166/java-lang-classcastexception-dtoobject-cannot-be-cast-to-dtoobjectmybatis

When you use DevTools with caching, you need to be aware of this limitation.架構

When the object is serialized into the cache, the application class loader is C1. Then after you change some code/configuration, devtools automatically restart the context and creates a new classloader (C2). When you hit that cache method, the cache abstraction finds an entry in the cache and it deserializes it from the store. If the cache library doesn't take the context classloader into account, that object will have the wrong classloader attached to it (which explains that weird exception A cannot be cast to A).app

TL;DR do not serialize classes with devtools if the cache library doesn't use the context classloader. Or put your cache library in the application classloader:spring-boot

幹掉 spring-boot-devtools 終於搞定了this

更多架構、PHP、GO相關踩坑實踐技巧請關注個人公衆號

相關文章
相關標籤/搜索