• 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());
            }
        }
    }
    
    
    最后

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

    总结

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

  • 相关阅读:
    Oracle基本概念
    md5密码生成工具
    tab页中不借用iframe的写法
    梅花雪树2.0和测试例子
    JS按比例缩放图片
    ASP.NET 文件下载
    删除VS2008最近打开文件或最近打开项目;重新另存项目的.sln文件
    去掉WINDOWS 2003 SERVER 开机和关机的麻烦
    分别设置母版页和内容页控件的值
    动态修改页面标题,关键字及描述等信息
  • 原文地址:https://www.cnblogs.com/guoyuchuan/p/11454529.html
Copyright © 2020-2023  润新知