记录一下 根据注解进行时间格式化 定义一个 自定义带参数的注解
接收参数 自定义注解时间格式化
针对于 各种类型的时间类型 进行格式化(LocalDateTime,LocalDate,Date)
自定义注解
//@Retention(rɪˈtenʃ(ə)n)是用来修饰注解的,它定义了该注解被保留时间的长短,是注解的注解,是JAVA元注解之一。
//SOURCE:注释将被编译器丢弃
//CLASS:注释将由编译器记录在类文件中,但不需要在运行时由VM保留。这是默认的行为。
//RUNTIME:注释将由编译器记录在类文件中,并在运行时由VM保留,因此可以反射性地读取它们。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD})
//@JacksonAnnotationsInside 标记注解,用于表示自定义注解包含 Jackson 注解;用于允许“注释包”,使用 Jackson 注释注释的自定义注释
@JacksonAnnotationsInside
//序列化 加载实现类型
@JsonSerialize(using = DateFormatSerializer.class)
public @interface JsonDateLocalizable {
//接收参数
public String dateFormat() default "";
}
序列化实现类
@NoArgsConstructor //创建构建无参构建函数
public class DateFormatSerializer extends JsonSerializer<Object> implements ContextualSerializer {
//接收参数
private String dateFormatKey;
//有参构建函数
public DateFormatSerializer(String dateFormatKey) {
this.dateFormatKey = dateFormatKey;
}
//序列化 数据处理方法实现
@Override
public void serialize(Object dateObject, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if(StrUtil.isEmpty(this.dateFormatKey)){
this.dateFormatKey="yyyy-MM-dd HH:mm:ss";
}
if (dateObject != null) {
if(dateObject instanceof LocalDateTime){
LocalDateTime localDateTime = (LocalDateTime) dateObject;
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(dateFormatKey);
String formatVal = localDateTime.format(dtf);
jsonGenerator.writeString(formatVal);
}
if(dateObject instanceof LocalDate){
LocalDate localDate = (LocalDate) dateObject;
DateTimeFormatter dtf = DateTimeFormatter.ofPattern(dateFormatKey);
String formatVal = localDate.format(dtf);
jsonGenerator.writeString(formatVal);
}
if(dateObject instanceof Date){
Date date = (Date) dateObject;
SimpleDateFormat sf = new SimpleDateFormat(dateFormatKey);
String formatVal = sf.format(date);
jsonGenerator.writeString(formatVal);
}
}
}
//实现 方法 createContextual 获取上下文参数
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
if (prov != null) { // 为空直接跳过
if (Objects.equals(property.getType().getRawClass(), LocalDateTime.class)// 判断数据类型是否是 符合要求 不是 直接跳过
||Objects.equals(property.getType().getRawClass(), LocalDate.class)
||Objects.equals(property.getType().getRawClass(), Date.class)) {
// 查找与此属性关联的注释的方法; 用于访问属性的实体之一关联的含义注释
JsonDateLocalizable jsonDateLocalizable = property.getAnnotation(JsonDateLocalizable.class);
if (jsonDateLocalizable == null) {
//查找与此属性的上下文关联的注释的方法;通常是声明成员的类(如果处理子类型则是其子类型)。
jsonDateLocalizable = property.getContextAnnotation(JsonDateLocalizable.class);
}
// 获取到注解相关的信息 有参构造函数 进行实例化
if (jsonDateLocalizable != null&&StrUtil.isNotBlank(jsonDateLocalizable.dateFormat())) { // 如果能得到注解,就将注解的 value 传入 SensitiveInfoSerialize
return new DateFormatSerializer(jsonDateLocalizable.dateFormat());
}
if(Objects.equals(property.getType().getRawClass(), LocalDateTime.class)){
return new DateFormatSerializer("yyyy-MM-dd HH:mm:ss");
}
if(Objects.equals(property.getType().getRawClass(), LocalDate.class)){
return new DateFormatSerializer("yyyy-MM-dd");
}
if(Objects.equals(property.getType().getRawClass(), Date.class)){
return new DateFormatSerializer("yyyy-MM-dd");
}
}
//但采用完全支持泛型的类型而不是原始类。这对于准确处理外部类型信息、处理多态类型是必要的。
//此调用还将在返回序列化器之前对其进行上下文化。
return prov.findValueSerializer(property.getType(), property);
}
//方法得到序列化的序列化器使用null值指定的属性。
return prov.findNullValueSerializer(property);
}
实体类
@Data
public class userVo implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
@ApiModelProperty(value ="ID")
private Long id;
@ApiModelProperty(value ="用户ID")
private Long userID;
@ApiModelProperty(value ="用户商Name")
private String usertName;
@JsonDateLocalizable()
@ApiModelProperty(value ="上传时间")
private LocalDateTime uploadTime;
}
ContextualSerializer
jsonserialalizer可以实现一个附加接口,以获得一个回调,该回调可用于创建序列化器的上下文实例,用于处理受支持类型的属性。这对于可以通过注释配置的序列化器很有用,或者根据被序列化的属性类型有不同的行为。
注意,在序列化器既需要上下文化又需要解析的情况下——也就是说,同时实现这个接口和ResolvableSerializer——首先通过ResolvableSerializer进行解析,然后再进行上下文解析(通过这个接口)。