Generi c RedisTemplate с использованием Jackson2JsonRedisSerializer в Kotlin - PullRequest
0 голосов
/ 11 января 2020

Мой контроллер использует шаблон redis для получения и установки данных из redis

val redisTemplate: RedisTemplate<String, Game>

Шаблон внедряется с использованием компонента

@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
}

Это работает, однако Я должен был четко указать, что класс верхнего уровня сериализуется, и поэтому возвращаемый шаблон будет работать только для 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

1 Ответ

1 голос
/ 14 января 2020

Я не смог найти решение, чтобы сохранить бобовое обобщение c. Если я сделаю тип reified, то я также должен сделать функцию встроенной, а затем либо частной, либо конечной. Это вызывает ошибки во время выполнения. Мое решение состоит в том, чтобы переместить обобщенный код c в частную встроенную функцию, а затем объявить 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()
...