在 Kotlin 中使用 Jackson2JsonRedisSerializer 的通用 RedisTemplate
Generic RedisTemplate using Jackson2JsonRedisSerializer in Kotlin
我的控制器使用redis模板从redis获取和设置数据
val redisTemplate: RedisTemplate<String, Game>
使用bean注入模板
@Bean
fun <T> redisTemplate(builder: RestTemplateBuilder): RedisTemplate<String, T> {
val serializer = Jackson2JsonRedisSerializer(Game::class.java)
serializer.setObjectMapper(objectMapper)
val template = RedisTemplate<String, T>()
template.setConnectionFactory(connectionFactory())
template.setDefaultSerializer(serializer)
return template
}
这有效,但是我必须明确说明顶层 class 正在序列化,因此返回的模板仅适用于 RedisTemplate<String, Game>
而不适用于 RedisTemplate<String, T>
。
我已尝试将序列化器实例化更改为以下内容,但它无法编译。
val serializer = Jackson2JsonRedisSerializer(T::class.java)
我试过改成下面的样子
val serializer = Jackson2JsonRedisSerializer(Object::class.java)
这可以编译,但从 redis 读取时出现异常
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.noicesoftware.redis.model.Game (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.noicesoftware.redis.model.Game is in unnamed module of loader 'app')
我已尝试使用 GenericJackson2JsonRedisSerializer,但我得到了上述行为和异常。
val serializer = GenericJackson2JsonRedisSerializer(objectMapper)
如有任何想法,我们将不胜感激。完整代码可在此处获得; https://github.com/DangerousDarlow/springboot-redis
我一直无法找到保持 bean 通用的解决方案。如果我使类型具体化,那么我还必须使函数内联 which 然后是 private 或 final。这会导致运行时错误。我的解决方案是将通用代码移动到私有内联函数中,然后为我想要的每个模板类型声明一个 bean。没有我希望的那么整洁,但我想还不错。
private inline fun <reified T> getRedisTemplate(): RedisTemplate<String, T> {
val serializer = Jackson2JsonRedisSerializer(T::class.java)
serializer.setObjectMapper(objectMapper)
val template = RedisTemplate<String, T>()
template.setConnectionFactory(connectionFactory())
template.setDefaultSerializer(serializer)
return template
}
@Bean
fun redisTemplate(): RedisTemplate<String, Game> = getRedisTemplate()
我的控制器使用redis模板从redis获取和设置数据
val redisTemplate: RedisTemplate<String, Game>
使用bean注入模板
@Bean
fun <T> redisTemplate(builder: RestTemplateBuilder): RedisTemplate<String, T> {
val serializer = Jackson2JsonRedisSerializer(Game::class.java)
serializer.setObjectMapper(objectMapper)
val template = RedisTemplate<String, T>()
template.setConnectionFactory(connectionFactory())
template.setDefaultSerializer(serializer)
return template
}
这有效,但是我必须明确说明顶层 class 正在序列化,因此返回的模板仅适用于 RedisTemplate<String, Game>
而不适用于 RedisTemplate<String, T>
。
我已尝试将序列化器实例化更改为以下内容,但它无法编译。
val serializer = Jackson2JsonRedisSerializer(T::class.java)
我试过改成下面的样子
val serializer = Jackson2JsonRedisSerializer(Object::class.java)
这可以编译,但从 redis 读取时出现异常
java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.noicesoftware.redis.model.Game (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.noicesoftware.redis.model.Game is in unnamed module of loader 'app')
我已尝试使用 GenericJackson2JsonRedisSerializer,但我得到了上述行为和异常。
val serializer = GenericJackson2JsonRedisSerializer(objectMapper)
如有任何想法,我们将不胜感激。完整代码可在此处获得; https://github.com/DangerousDarlow/springboot-redis
我一直无法找到保持 bean 通用的解决方案。如果我使类型具体化,那么我还必须使函数内联 which 然后是 private 或 final。这会导致运行时错误。我的解决方案是将通用代码移动到私有内联函数中,然后为我想要的每个模板类型声明一个 bean。没有我希望的那么整洁,但我想还不错。
private inline fun <reified T> getRedisTemplate(): RedisTemplate<String, T> {
val serializer = Jackson2JsonRedisSerializer(T::class.java)
serializer.setObjectMapper(objectMapper)
val template = RedisTemplate<String, T>()
template.setConnectionFactory(connectionFactory())
template.setDefaultSerializer(serializer)
return template
}
@Bean
fun redisTemplate(): RedisTemplate<String, Game> = getRedisTemplate()