SpringBoot 시간 매개 변수 처리 전체 솔 루 션

자바 웹 프로그램의 개발 과정 에서 인 터 페 이 스 는 앞 뒤 가 연결 되 는 주요 창 이 고 인터페이스 매개 변수의 수신 은 가끔 골 치 아 픈 일이 다.그 중에서 프로그램 원숭이 를 가장 괴 롭 히 는 것 은 시간 매개 변수의 수신 이 어야 한다.
예 를 들 어 한 사용자 의 만 료 시간 을 설정 하고 전단 은 도대체 어떤 형식 으로 파 라 메 터 를 전달 합 니까?타임 스탬프?아니면 2019-12-01 22:13:00 이런 격식?아니면 다른 형식?
오늘 은 SpringBoot Web 응용 인터페이스 수신 시간 유형 매개 변수 에 대한 문제 해결 방안 을 정리 하 겠 습 니 다.
주:현재 저 는 Spring 소스 코드 에 대한 파악 이 아직 좋 지 않 기 때문에 이 편 은 해결 방법 만 정리 하고 나중에 많이 깨 달 으 면 다시 쓰 겠 습 니 다!
예제 코드 로 이동 하 십시오:https://github.com/laolunsi/spring-boot-examples
간단 한 테스트 를 통 해 우 리 는 알 고 있다.
  • @RequestBody 주 해 를 사용 하지 않 는 경우 모든 시간 유형 매개 변 수 는 오 류 를 일 으 킬 수 있 습 니 다.
  • @RequestBody 를 사용 하여 전단 전달 시간 스탬프 또는 2019-11-22 형식 이 정상 적 이 고 전달 2019-11-22 11:22:22 에 잘못 보 고 했 으 며 다른 형식 도 잘못 보 고 했 습 니 다.
  • 이전에 유사 한 해결 방법 을 접 한 적 이 있 습 니 다.클래스 의 속성 에@DateFormat 주 해 를 추가 하여 단일 시간 매개 변수 문 제 를 해결 합 니 다.
    하지만 한계 가 많다.
    이상 적 인 해결 방안 은:한 번 의 설정,전역 적 으로 통용 되 고 다양한 형식,자동 변환(입 에 잘 맞습니다)
    1.소스 코드 요약 분석
    우선 소스 코드 를 간단하게 분석 해 보 겠 습 니 다.

    깊이 들 어가 면 설명 안 해.🤦‍♂️)
    쉽게 말 하면 인터페이스 에서 받 은 인 자 는 먼저 HandlerMethodArgument Resolver 의 실현 클래스 에 의 해 처리 되 었 고 이 를 우리 가 필요 로 하 는 형식 으로 바 꾸 었 다.
    여 기 는 주로 두 가지 상황 으로 나 뉜 다.
  • @RequestBody 의 인 자 를 사 용 했 습 니 다.보통 대상 이 수신 하고 전단 은 보통 JSON 형식
  • 으로 전 달 됩 니 다.
  • 다른 매개 변 수 를 받 는 방식,예 를 들 어@RequestAttribute,@RequestParam 또는 기본 형식,전단 은 보통 폼 파라미터,요청 URL 접미사 파라미터 등
  • 을 전달 합 니 다.
    해결 방법
  • 기본 형식 이나@RequestAttribute 를 사용 하거나@RequestParam 을 사용 합 니 다.이러한 매개 변 수 는 converter 설정 을 통 해 문 제 를 해결 합 니 다
  • @RequestBody 에서 분석 한 인 자 를 사용 하여 Object Mapper 에 직렬 화 와 반 직렬 화 규칙 을 설정 하여 처리 합 니 다
  • 2.1 사용자 정의 컨버터
    첫 번 째 상황 에 대해 우 리 는 converter 를 설정 해 야 합 니 다.여기 서 두 가지 방법 을 소개 합 니 다.
  • @ControllerAdvice + @InitBinder
  • @Bean 정의 converter 클래스 를 직접 사용 합 니 다
  • 우선,DateConverter 클래스 가 필요 합 니 다.이 클래스 는 Converter 인 터 페 이 스 를 실현 하고 그 중의 convert 방법 을 다시 써 서 String 을 Date 형식 으로 바 꿉 니 다.
    우 리 는 세 가지 처리 형식 을 정의 했다.
    
    /**
     *      
     *      、      、      Date  
     */
    /*@Deprecated*/
    public class DateConverter implements Converter<String, Date> {
    
     private Logger logger = LoggerFactory.getLogger(DateConverter.class);
    
     private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
     private static final String shortDateFormat = "yyyy-MM-dd";
     private static final String timeStampFormat = "^\\d+$";
    
     @Override
     public Date convert(String value) {
      logger.info("    :" + value);
    
      if(value == null || value.trim().equals("") || value.equalsIgnoreCase("null")) {
       return null;
      }
    
      value = value.trim();
    
      try {
       if (value.contains("-")) {
        SimpleDateFormat formatter;
        if (value.contains(":")) {
         formatter = new SimpleDateFormat(dateFormat);
        } else {
         formatter = new SimpleDateFormat(shortDateFormat);
        }
        return formatter.parse(value);
       } else if (value.matches(timeStampFormat)) {
        Long lDate = new Long(value);
        return new Date(lDate);
       }
      } catch (Exception e) {
       throw new RuntimeException(String.format("parser %s to Date fail", value));
      }
      throw new RuntimeException(String.format("parser %s to Date fail", value));
     }
    }
    
    
    주:이 DateConverter 류 는 아래 에서 모두 사용 합 니 다.
    
    import com.aegis.yqmanagecenter.config.date.DateConverter;
    import com.aegis.yqmanagecenter.model.bean.common.JsonResult;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.propertyeditors.CustomDateEditor;
    import org.springframework.core.convert.support.GenericConversionService;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.annotation.*;
    
    import java.beans.PropertyEditorSupport;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    @ControllerAdvice
    public class ControllerHandler {
    
     private Logger logger = LoggerFactory.getLogger(ControllerHandler.class);
    
     @InitBinder
     public void initBinder(WebDataBinder binder) {
      //   1,  converter
      GenericConversionService genericConversionService = (GenericConversionService) binder.getConversionService();
      if (genericConversionService != null) {
       genericConversionService.addConverter(new DateConverter());
      }
    
      //   2,          ,        ,    dateEditor,      
      DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
      CustomDateEditor dateEditor = new CustomDateEditor(df, true);
      binder.registerCustomEditor(Date.class, dateEditor);
    
    
      //   3,    converter
      binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
       @Override
       public void setAsText(String text) throws IllegalArgumentException {
        setValue(new DateConverter().convert(text));
       }
      });
    
     }
    }
    
    
    주:위의 세 가지 방법 은 모두@Controller Advice+@InitBinder 를 이용 하여 시간 매개 변 수 를 설정 하여 처리 합 니 다.그 중에서 1 과 3 은 DateConverter 를 설정 할 수 있 고 방법 2 는 하나의 수 동 으로 형식 을 설정 할 수 있 습 니 다.
    위 설정 방법 으로 는 JSon 형식 데이터 의 시간 매개 변수 수신 문 제 를 해결 할 수 없습니다.다음은 완전한 해결 방안 인 DateConverter 를 구성 요소 로 등록 하고 Object Mapper 를 사용 하여 시간 매개 변수의 직렬 화(인터페이스 반환 값)와 반 직렬 화 형식(인터페이스 수신 매개 변수)을 설정 합 니 다.
    2.2 ObjectMapper 설정 및 전체 솔 루 션
    완전한 해결 방안:
    
    /**
     *       
     *   @RequestAttribute、@RequestParam @RequestBody                  
     */
    @Configuration
    public class DateConfig {
    
     /**
      *         
      */
     public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
     /**
      * Date   ,    RequestParam PathVariable  
      */
     @Bean
     public Converter<String, Date> dateConverter() {
      return new DateConverter();
     }
    
     /**
      * Json           ,    Post     json                 json
      *   @RequestBody       Date         
      */
     @Bean
     public ObjectMapper objectMapper(){
      ObjectMapper objectMapper = new ObjectMapper();
      objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
      objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
    
      JavaTimeModule javaTimeModule = new JavaTimeModule();
    
      //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 {
        return new DateConverter().convert(jsonParser.getText());
       }
      });
    
      objectMapper.registerModule(javaTimeModule);
      return objectMapper;
     }
    
    }
    참고:약서-Spring 에 서 는 LocalDateTime,LocalDate 등 매개 변 수 를 참조 로 사용 합 니 다.
    이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

    좋은 웹페이지 즐겨찾기