SpringMVC Jackson/Fastjson 使用 @RequestParam/@PathVariable/@RequestBody 接收 LocalDateTime 参数对象,可时间戳

x33g5p2x  于2021-11-22 转载在 Spring  
字(6.3k)|赞(0)|评价(0)|浏览(254)

我的预想是支持多种格式,还支持时间戳,直接上代码(要用 Fastjson 看文末参考)

时间配置类:

import org.csaarg.util.DateUtils;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;

/** * Spring 中使用 LocalDateTime、LocalDate 等参数作为入参:https://www.jianshu.com/p/b52db905f020 * * @author duanluan */
@Configuration
public class DateConfig {

  /** * 默认日期时间格式 */
  public static final String DEFAULT_DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
  public static final String DEFAULT_NEW_DATE_TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
  // /**
  // * 默认日期格式
  // */
  // public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
  // /**
  // * 默认时间格式
  // */
  // public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";

  /** * 使用 RequestParam 或 PathVariable 注解时 String 转 LocalDate */
  @Bean
  public Converter<String, LocalDate> localDateConverter() {
    return new Converter<String, LocalDate>() {
      @Override
      public LocalDate convert(String source) {
        return DateUtils.parseLocalDate(source);
      }
    };
  }

  /** * 使用 RequestParam 或 PathVariable 注解时 String 转 LocalDateTime */
  @Bean
  public Converter<String, LocalDateTime> localDateTimeConverter() {
    return new Converter<String, LocalDateTime>() {
      @Override
      public LocalDateTime convert(String source) {
        return DateUtils.parseLocalDateTime(source);
      }
    };
  }

  /** * Json 序列化和反序列化转换器,用于转换 Post 请求体中的 json 以及将我们的对象序列化为返回响应的 json */
  @Bean
  public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);

    // LocalDateTime 系列序列化和反序列化模块,继承自 jsr310,我们在这里修改了日期格式
    JavaTimeModule javaTimeModule = new JavaTimeModule();
    // javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN)));
    javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateUtils.getDefaultFormatter(null, DateUtils.PATTERN_UUUU_MM_DD)));
    // javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_PATTERN)));
    javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateUtils.getDefaultFormatter(null, DateUtils.PATTERN_UUUU_MM_DD_HH_MM_SS)));
    // javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));
    javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateUtils.getDefaultFormatter(null, DateUtils.PATTERN_HH_MM_SS)));

    javaTimeModule.addDeserializer(LocalDate.class, new JsonDeserializer<LocalDate>() {
      @Override
      public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        return DateUtils.parseLocalDate(jsonParser.getText());
      }
    });
    javaTimeModule.addDeserializer(LocalDateTime.class, new JsonDeserializer<LocalDateTime>() {
      @Override
      public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        return DateUtils.parseLocalDateTime(jsonParser.getText());
      }
    });
    // javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_PATTERN)));
    javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateUtils.getDefaultFormatter(null, DateUtils.PATTERN_HH_MM_SS)));

    // 序列化:Date 转字符串
    javaTimeModule.addSerializer(Date.class, new JsonSerializer<Date>() {
      @Override
      public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);
        jsonGenerator.writeString(dateFormat.format(date));
      }
    });
    // 反序列化:字符串转 Date
    javaTimeModule.addDeserializer(Date.class, new JsonDeserializer<Date>() {
      @Override
      public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        String source = jsonParser.getText();
        SimpleDateFormat dateFormat = new SimpleDateFormat(DEFAULT_DATE_TIME_PATTERN);
        try {
          return dateFormat.parse(source);
        } catch (ParseException e) {
          dateFormat = new SimpleDateFormat(DEFAULT_NEW_DATE_TIME_PATTERN);
          try {
            return dateFormat.parse(source);
          } catch (ParseException parseException) {
            throw new RuntimeException(e);
          }
        }
      }
    });

    objectMapper.registerModule(javaTimeModule);
    return objectMapper;
  }

}

Spring MVC 配置:

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/** * Spring MVC 配置 * * @author duanluan */
@Configuration
public class MvcConfig implements WebMvcConfigurer {

  // 时间配置
  @Autowired
  private DateConfig dateConfig;

  /** * Jackson 转换 * * @return */
  @Bean
  public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

    // 根据时间配置获取 ObjectMapper
    ObjectMapper objectMapper = dateConfig.objectMapper();

    // 忽略前端传递过来但是 @RequestBody 注解的对象中没有的参数(https://www.jianshu.com/p/83a170baf10c),相当于在实体类中添加 @JsonIgnoreProperties(ignoreUnknown = true)
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    converter.setObjectMapper(objectMapper);
    return converter;
  }
}

相关类

Java 8 时间工具类:DateUtils

注意

在 DateConfig 中定义了一个 ObjectMapper,有其他地方需要配置这个对象的时候,比如 MappingJackson2HttpMessageConverter,需要 @Autowired DateConfig 后用 objectMapper () 方法。

参考

相关文章

微信公众号

最新文章

更多