zoukankan      html  css  js  c++  java
  • springboot处理date参数

    该图片由grebmot在Pixabay上发布

    前言

    最近在后台开发中遇到了时间参数的坑,就单独把这个问题提出来找时间整理了一下;

    正文

    测试方法

    bean代码:

    
    public class DateModelNoAnnotation {
        private Integer id;
        private Date receiveDate;
    }
        
    

    controller代码:

    
    @RestController
    @RequestMapping("/date")
    public class DateVerifyController {
        //    方式一
        @PostMapping("/no")
        public String dateUnNoAnnotation(DateModelNoAnnotation dateModelNoAnnotation){
            System.out.println(dateModelNoAnnotation.toString());
            return "SUCCESS";
        }
    
    //    方式二
        @PostMapping("/has")
        public String dateHasAnnotation(@RequestBody DateModelNoAnnotation dateModelNoAnnotation){
            System.out.println(dateModelNoAnnotation.toString());
            return "SUCCESS";
        }
    //    方式三
        @GetMapping("/param")
        public String dateParams(@RequestParam("id")Integer id, @RequestParam("receiveDate")Date receiveDate){
            System.out.println("id====="+id);
            System.out.println("receiveDate====="+receiveDate);
            System.out.println("receiveDate====="+receiveDate.getTime());
            return "SUCCESS";
        }
    //    方式四
        @GetMapping("/no/param")
        public String dateNoParams(Integer id,Date receiveDate){
            System.out.println("id====="+id);
            System.out.println("receiveDate====="+receiveDate);
            System.out.println("receiveDate====="+receiveDate.getTime());
            return "SUCCESS";
        }
    }
    
    

    接收参数的几种方式(实验)

    1. 通过bean来接收数据(表单方式)
    • 这种方式只支持"yyyy/MM/dd HH:mm:ss"这种格式的time参数
    1. 通过bean来接收数据(json格式)
    • 这种方式只支持"yyyy-MM-dd HH:mm:ss"这种格式的time参数
    1. 通过RequestParam注解
    • 这种方式只支持"yyyy/MM/dd HH:mm:ss"这种格式的time参数
    1. 不通过RequestParam注解
    • 这种方式只支持"yyyy/MM/dd HH:mm:ss"这种格式的time参数

    以上几种接收参数的方式接收的参数格式并不统一,而且有时候web前端传入的时间参数为时间戳,还得写修改接口或者让其自己修改格式;
    后端给前端统一返回json格式的数据,且时间格式为"yyyy-MM-dd HH:mm:ss"

    解决方案

    开发之前统一时间接口接收的时间格式

    一 yyyy/MM/dd HH:mm:ss 格式

    后端所有接口统一接收"yyyy/MM/dd HH:mm:ss"或"yyyy/MM/dd"格式时间参数

    第一种: 舍弃上边的方式二的接口

    第二种:不舍弃方拾二,在bean的时间属性上添加JsonFormat注解,例如:

    
        com.fasterxml.jackson.annotation.JsonFormat;
        
        @JsonFormat(timezone = "GMT+8",pattern = "yyyy/MM/dd HH:mm:ss")
        private Date receiveDate;
        
    

    优势: 不舍弃方式二接口,且统一了时间格式

    使用该注解的弊端: 当pattern="yyyy/MM/dd" 时, 只支持处理“2019/09/03"格式时间参数,不支持“2019/09/03 00:00:00”,且会报错,当pattern="yyyy/MM/dd HH:mm:ss"时,只支持处理“2019/09/03 00:00:00"格式时间参数,其余格式均会报错;

    二 接收所有时间格式

    • yyyy-MM-dd HH:mm:ss 格式
    • yyyy-MM-dd 格式
    • 时间戳
    • yyyy/MM/dd HH:mm:ss 格式
    • yyyy/MM/dd 格式
    注意

    该方式不对json或xml的数据处理,比如使用@RequestBody注解的bean(也就是方式二)

    工具类:

    
    import org.springframework.core.convert.converter.Converter;
    import org.springframework.util.StringUtils;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    /**
     * @author gyc
     * @title: DateConverter
     * @projectName app
     * @date 2019/8/1914:36
     * @description: 时间转换类
     */
    public class CourseDateConverter implements Converter<String, Date> {
        private static final String dateFormat = "yyyy-MM-dd HH:mm:ss";
        private static final String dateFormata = "yyyy-MM-dd HH:mm:ss";
        private static final String shortDateFormat = "yyyy-MM-dd";
        private static final String shortDateFormata = "yyyy/MM/dd";
        private static final String timeStampFormat = "^\d+$";
        @Override
        public Date convert(String value) {
            if(StringUtils.isEmpty(value)) {
                return null;
            }
            value = value.trim();
            try {
                if (value.contains("-")) {
                    SimpleDateFormat formatter;
                    if (value.contains(":")) {
                        //yyyy-MM-dd HH:mm:ss 格式
                        formatter = new SimpleDateFormat(dateFormat);
                    } else {
                        //yyyy-MM-dd 格式
                        formatter = new SimpleDateFormat(shortDateFormat);
                    }
                    return formatter.parse(value);
                } else if (value.matches(timeStampFormat)) {
                    //时间戳
                    Long lDate = new Long(value);
                    return new Date(lDate);
                }else if (value.contains("/")){
                    SimpleDateFormat formatter;
                    if (value.contains(":")) {
    //                    yyyy/MM/dd HH:mm:ss 格式
                        formatter = new SimpleDateFormat(dateFormata);
                    } else {
    //                    yyyy/MM/dd 格式
                        formatter = new SimpleDateFormat(shortDateFormata);
                    }
                    return formatter.parse(value);
                }
            } 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));
        }
    }
    
    
    将时间转换类应用到接口上

    介绍两种方式:使用@Component + @PostConstruct或@ControllerAdvice + @InitBinder

    第一种方式:

    @Component + @PostConstruct
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.convert.support.GenericConversionService;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.support.ConfigurableWebBindingInitializer;
    import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
    import javax.annotation.PostConstruct;
    
    @Component
    public class WebConfigBeans {
      @Autowired
      private RequestMappingHandlerAdapter handlerAdapter;
      @PostConstruct
      public void initEditableAvlidation() {
        ConfigurableWebBindingInitializer initializer = (ConfigurableWebBindingInitializer)handlerAdapter.getWebBindingInitializer();
        if(initializer.getConversionService()!=null) {
          GenericConversionService genericConversionService = (GenericConversionService)initializer.getConversionService();
    
          genericConversionService.addConverter(new DateConverterConfig());
    
        }
      }
    }
    
    

    第二种方式:

    @ControllerAdvice + @InitBinder
    
    import com.aegis.config.converter.DateConverter;
    import com.aegis.model.bean.common.JsonResult;
    import org.springframework.core.convert.support.GenericConversionService;
    import org.springframework.http.HttpStatus;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.annotation.*;
    @ControllerAdvice
    public class CourseControllerHandler {
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            GenericConversionService genericConversionService = (GenericConversionService) binder.getConversionService();
            if (genericConversionService != null) {
                genericConversionService.addConverter(new CourseDateConverter());
            }
        }
    }
    
    
    最后

    我使用的最后的一种方法的第二种方式

    总结

    时间参数这个坑还是有点大的,之前都是针对性的处理,只要一变化就没法了;现在这个还是可以应付基本上会出现的错误了;

  • 相关阅读:
    LeetCode Array Easy 414. Third Maximum Number
    LeetCode Linked List Medium 2. Add Two Numbers
    LeetCode Array Easy 283. Move Zeroes
    LeetCode Array Easy 268. Missing Number
    LeetCode Array Easy 219. Contains Duplicate II
    LeetCode Array Easy 217. Contains Duplicate
    LeetCode Array Easy 189. Rotate Array
    LeetCode Array Easy169. Majority Element
    LeetCode Array Medium 11. Container With Most Water
    LeetCode Array Easy 167. Two Sum II
  • 原文地址:https://www.cnblogs.com/guoyuchuan/p/11454529.html
Copyright © 2011-2022 走看看