前言

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

正文

测试方法

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

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

总结

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

最新文章

  1. 也许你需要点实用的-Web前端笔试题
  2. Python解析非标准JSON(Key值非字符串)
  3. HTML中的div,section,article的区别
  4. Babelfish(二分查找,字符串的处理略有难度,用sscanf输入)
  5. bzoj 1493 暴力
  6. CountDownLatch,一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。
  7. IOS小知识纪录
  8. File Operation using SHFileOperation
  9. The test form is only available for requests from the local machine 解决方法
  10. 使用token机制来验证用户的安全性-b
  11. mysql数据库学习(二)--表操作
  12. Qt对xml文件的读写
  13. 微信小程序怎么做出前端table的效果
  14. Ant + Jenkies +Tomcat 自动构建部署Web项目
  15. openlayers4 入门开发系列之热力图篇(附源码下载)
  16. 服务器配置 ssl 证书
  17. 梯度下降与pytorch
  18. 全网最详细的HBase启动以后,HMaster进程启动了,几秒钟以后自动关闭问题的解决办法(图文详解)
  19. ORACLE COMMENTON 使用
  20. [UOJ240]aliens

热门文章

  1. electron项目中使用js web worker时,new worker(path)路径问题
  2. ORACLE监听理解
  3. c# MVC5(一) 初步认识以及新建mvc
  4. VS2015秘钥激活
  5. (原)Ubuntu安装TensorRT
  6. 学Redis
  7. java 深copy
  8. django 权限设置
  9. 遇到libgflags.a(gflags.cc.o): relocation R_X86_64_32 against `.rodata.str1.1&#39; ca时
  10. 201871010134-周英杰《面向对象程序设计(Java)》第四周学习总结