У меня есть такой метод в Java:
@Bean(name = "redisZSetTemplate")
<T> RedisTemplate<String, T> redisTemplateZSet(RedisConnectionFactory redisConnectionFactory) {
}
что я должен сделать, чтобы получить тип T, например T.getClass() или T.class? Я пробовал так, добавляю import com.fasterxml.jackson.core.type.TypeReference;, затем получаю класс T следующим образом:
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(new TypeReference<T>(){}.getClass());
кажется, new TypeReference<T>(){}.getClass() получить текущий класс метода. не тип класса T。 Я хочу получить тип, потому что я хочу проанализировать тип данных при извлечении из Redis. это полный код выглядит так:
@Bean(name = "redisZSetTemplate")
<T> RedisTemplate<String, T> redisTemplateZSet(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, T> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setEnableTransactionSupport(true);
Class<T> tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(tClass);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(serializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
сохраните объект ArticleZSet в redis zset и десериализуйте его из redis. На самом деле я думаю, что определение T более простое, что я делаю следующим образом:
@Bean(name = "redisObjectTemplate")
RedisTemplate<String, Object> redisTemplateObject(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setEnableTransactionSupport(true);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(serializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
/**
* @return
*/
@Bean(name = "redisIntegerTemplate")
RedisTemplate<String, Integer> redisTemplateInt(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Integer> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setEnableTransactionSupport(true);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(serializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
/**
* @return
*/
@Bean(name = "redisLongTemplate")
RedisTemplate<String, Long> redisTemplateLong(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Long> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
template.setEnableTransactionSupport(true);
Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Long.class);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
serializer.setObjectMapper(mapper);
template.setValueSerializer(serializer);
template.setKeySerializer(new StringRedisSerializer());
template.setHashKeySerializer(serializer);
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
Я должен определить каждый шаблон для разных типов данных, что делает код уродливым. Более простой способ: я хочу просто определить 1 шаблон и общий тип данных, который может сделать код более простым и пригодным для повторного использования.
Пожалуйста, разверните свой пример, чтобы объяснить, почему вы хотите получить тип.
Я добавил некоторый контент, объясняющий, почему я хочу получить тип T, когда я десериализовал дату, полученную из redis zset, мне нужно десериализовать ее и использовать на следующем шаге. @tgdavies
Предположительно, когда вы звоните redisTemplateZSet, вы знаете, что такое T. Можете ли вы просто передать класс в качестве параметра?
На самом деле ... предложение Тдэвиса - единственный общий подход, который сработает. И именно это решение предлагает stackoverflow.com/a/3437930/139985. Так что на самом деле дублирующая ссылка, предложенная kaya3, является правильной ссылкой ... и ... вы не прочитали ее должным образом.
Хотя может быть сложно применить решение в вашем случае использования, это единственное универсальное решение. Возможно, вы сможете сделать что-то хакерское с помощью собственного класса десериализатора, который проверяет сериализованные данные и выбирает класс для T на основе того, что он находит.
Или... вы можете попробовать применить github.com/spring-projects/spring-data-redis/pull/2375 к локальной сборке Redis.




Можно ли получить тип из универсального типа в java.
Ответ на общий вопрос — нет, как объяснено в
и подобные вопросы. По сути, вы не можете получить класс T во время выполнения. Если вам нужно знать класс во время выполнения, его нужно либо передать как параметр java.lang.Class, либо вывести из фактического экземпляра типа T. (И последнее может быть надежно выполнено только в том случае, если T является листовым классом.)
На момент написания статьи прямого решения в сценарии использования Redis также не было.
Однако я наткнулся на неслитый запрос на извлечение, который утверждает, что поддерживает это в привязке Spring-Data Redis; см. пулл-реквест #2375. Если вы хотите попробовать это, вам нужно будет выяснить, как применить изменение к ... любой версии любой привязки Redis, которую вы на самом деле используете. Вероятно, это потребует создания (временной) вилки.
нет, я уже прочитал этот вопрос, и он не смог решить эту проблему. @kaya3