转化的工具类
- 因为多个地方要用 所以剥离出来
public class ObjectMapperUtils {
public static void registerTimeModule(ObjectMapper objectMapper){
// objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
JavaTimeModule javaTimeModule = new JavaTimeModule();
/**
* 演示:Date序列化为时间戳
*
* 通过继承JsonSerializer<Type> 抽象类(注意是泛型), 实现serialize方法实现
* 要被序列化的内容是:第一个参数
* 序列化的后内容是:jsonGenerator.writeString() 里的内容
*/
/* javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(String.valueOf(value.getTime()));
}
});
*/
/**
* 演示:时间戳反序列Date
*
* 通过继承JsonDeserializer<Type> 抽象类(注意是泛型), 实现deserialize 方法实现
* 要被反序列化的内容:JsonParser.getText()
* 反序列化后的内容是:返回值
*/
/*
javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String value = p.getText();
Long time=Long.valueOf(value);
Date date=new Date(time);
return date;
}
});
*/
//LocalDateTime系列序列化和反序列化模块,继承自jsr310,我们在这里修改了日期格式
javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
javaTimeModule.addSerializer(LocalDate.class,new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
javaTimeModule.addSerializer(LocalTime.class,new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDateTime.class,new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
javaTimeModule.addDeserializer(LocalDate.class,new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
javaTimeModule.addDeserializer(LocalTime.class,new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
//Date序列化和反序列化
javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
String formattedDate = formatter.format(date);
jsonGenerator.writeString(formattedDate);
}
});
javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
String date = jsonParser.getText();
try {
return format.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
});
objectMapper.registerModule(javaTimeModule);
}
}
前后端传参时的配置类
/**
* spring传递对象时 转化时间类型
*/
@Configuration
public class DateConvertConfig {
/** 默认日期时间格式 */
public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
/** 默认日期格式 */
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
/** 默认时间格式 */
public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
/**
* 演示:时间戳转化为Date
*
* 注入转换器Converter< , >
* 泛型的第一个参数是转换前的类型 泛型的第二个参数是转换后的类型
*/
/*
@Bean
public Converter<Long,Date> dateConverterByTimestap(){
return new Converter<Long, Date>() {
@Override
public Date convert(Long source) {
return new Date(source);
}
};
}
*/
/**
* LocalDate转换器,用于转换RequestParam和PathVariable参数
*/
@Bean
public Converter<String, LocalDate> localDateConverter() {
return new Converter<String, LocalDate>() {
@Override
public LocalDate convert(String source) {
return LocalDate.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT));
}
};
}
/**
* LocalDateTime转换器,用于转换RequestParam和PathVariable参数
*/
@Bean
public Converter<String, LocalDateTime> localDateTimeConverter() {
return new Converter<String, LocalDateTime>() {
@Override
public LocalDateTime convert(String source) {
return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT));
}
};
}
/**
* LocalTime转换器,用于转换RequestParam和PathVariable参数
*/
@Bean
public Converter<String, LocalTime> localTimeConverter() {
return new Converter<String, LocalTime>() {
@Override
public LocalTime convert(String source) {
return LocalTime.parse(source, DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT));
}
};
}
/**
* Date转换器,用于转换RequestParam和PathVariable参数
*/
@Bean
public Converter<String, Date> dateConverterByFormate() {
return new Converter<String,Date>(){
@Override
public Date convert(String source) {
SimpleDateFormat format = new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT);
try {
return format.parse(source);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
};
}
/**
* Json序列化和反序列化转换器,用于转换Post请求体中的json以及将我们的对象序列化为返回响应的json
*/
@Bean
public ObjectMapper objectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
ObjectMapperUtils.registerTimeModule(objectMapper);
return objectMapper;
}
}
Redis种存储时
@Configuration
@EnableCaching
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String,String>();
redisTemplate.setConnectionFactory(factory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
/**Jackson序列化 json占用的内存最小 */
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
/**
* 配置时间类的序列化与反序列化
* /
ObjectMapperUtils.registerTimeModule(om);
jackson2JsonRedisSerializer.setObjectMapper(om);
/**Jdk序列化 JdkSerializationRedisSerializer是最高效的*/
// JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
/**String序列化*/
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//设置序列化类型
/**将key value 进行stringRedisSerializer序列化*/
redisTemplate.setKeySerializer(stringRedisSerializer);
redisTemplate.setValueSerializer(stringRedisSerializer);
/**将HashKey HashValue 进行序列化*/
redisTemplate.setHashKeySerializer(stringRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
//配置Redis作二级缓存:注入redis中key的生成方式 到时可以在方法的注解上直接调用
@Bean
public KeyGenerator simpleKeyGenerator() {
return (o, method, objects) -> {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(o.getClass().getSimpleName());
stringBuilder.append(".");
stringBuilder.append(method.getName());
stringBuilder.append("[");
for (Object obj : objects) {
stringBuilder.append(obj.toString());
}
stringBuilder.append("]");
return stringBuilder.toString();
};
}
//配置Redis作二级缓存:配置CacheManager
@Bean
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
return new RedisCacheManager(
RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory),
//TODO 180
this.getRedisCacheConfigurationWithTtl(60), // 默认策略,未配置的 key 会使用这个
this.getRedisCacheConfigurationMap() // 指定 key 策略
);
}
//配置Redis作二级缓存:自定缓存策略
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
/**
*可以通过@Cacheable、@CachPut、@CachEvict注解中的value找到对应方法 然后设置过期时间
*/
//redisCacheConfigurationMap.put("注解中value的值", this.getRedisCacheConfigurationWithTtl(100));//单位是秒
return redisCacheConfigurationMap;
}
//配置Redis作二级缓存:给自定缓存策略设置序列化方式以及过期时间
private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
/**
* 配置时间类的序列化与反序列化
* /
ObjectMapperUtils.registerTimeModule(om);
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
redisCacheConfiguration = redisCacheConfiguration.serializeValuesWith(
//设置序列化方式
RedisSerializationContext
.SerializationPair
.fromSerializer(jackson2JsonRedisSerializer)
).entryTtl(Duration.ofSeconds(seconds)); //设置过期时间
return redisCacheConfiguration;
}
}
-
注意
- 一个类型只能默认生效一个转化器、一个序列化转化器、一个反序列化转化器
- 要使用配置好的序列化和反序列化转化器 就要使用 @Autowried 注入 ObjectMapper 而不是自己 new 一个
-
为什么要配置
- 因为就拿 LocalDateTime 来说,在redis反序列化的时候LocalDateTime没有无参构造函数 所以就没法反序列化
- 同时也为了前后端传参时方便,不然就要传递一个对象
-
如何实现其他类型转化(比如BigInteger等)
- 如何实现@RequestParam 注解处的转化
@Bean public Converter<String, BigInteger> bigIntegerConverter() { return new Converter<String, BigInteger>(){ }; }
- 如何实现Json的序列化和反序列化
SimpleModule simpleModule = new SimpleModule(); //序列化(如果是数组类型也可以 比如 BigInteger[].class) simpleModule.addSerializer(BigInteger.class, ,new JsonSerializer<BigInteger>(){ }); //反序列化 simpleModule.addDeserializer(BigInteger.class, ,new JsonDeserializer<BigInteger>(){ }); //注册该module mapper.registerModule(simpleModule)