SpringBoot对接收及返回Instant类型的处理(转)
一:处理post请求json中的Instant类型
1.springboot中日期格式化配置:
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
以上配置只对Date类型的日期格式化有效,对LocalDateTime ,Instant无效,需要添加以下配置:
package com.mycompany.myapp.config; import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.zalando.problem.ProblemModule;
import org.zalando.problem.violations.ConstraintViolationProblemModule; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.mycompany.myapp.utils.DateFormatUtil; @Configuration
public class JacksonConfiguration { @Value("${spring.jackson.date-format}")
private String formatValue; @Bean(name = "format")
public DateTimeFormatter format() {
return DateTimeFormatter.ofPattern(formatValue);
} @Bean
public ObjectMapper serializingObjectMapper(@Qualifier("format") DateTimeFormatter format) {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(format));
javaTimeModule.addSerializer(Instant.class, new InstantCustomSerializer(format));
javaTimeModule.addSerializer(Date.class, new DateSerializer(false, new SimpleDateFormat(formatValue)));
javaTimeModule.addDeserializer(Instant.class, new InstantCustomDeserializer());
javaTimeModule.addDeserializer(Date.class, new DateCustomDeserializer());
ObjectMapper mapper = new ObjectMapper()
.registerModule(new ParameterNamesModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.registerModule(javaTimeModule);
return mapper;
} class InstantCustomSerializer extends JsonSerializer<Instant> {
private DateTimeFormatter format; private InstantCustomSerializer(DateTimeFormatter formatter) {
this.format = formatter;
} @Override
public void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (instant == null) {
return;
}
String jsonValue = format.format(instant.atZone(ZoneId.systemDefault()));
jsonGenerator.writeString(jsonValue);
}
} class InstantCustomDeserializer extends JsonDeserializer<Instant>{ @Override
public Instant deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String dateString = p.getText().trim();
if(StringUtils.isNotBlank(dateString)){
Date pareDate;
try {
pareDate = DateFormatUtil.pareDate(dateString);
if(null != pareDate){
return pareDate.toInstant();
}
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
} } class DateCustomDeserializer extends JsonDeserializer<Date>{ @Override
public Date deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String dateString = p.getText().trim();
if(StringUtils.isNotBlank(dateString)){
try {
return DateFormatUtil.pareDate(dateString);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
} } /**
* Support for Java date and time API.
* @return the corresponding Jackson module.
*/
@Bean
public JavaTimeModule javaTimeModule() {
return new JavaTimeModule();
} @Bean
public Jdk8Module jdk8TimeModule() {
return new Jdk8Module();
} /*
* Support for Hibernate types in Jackson.
*/
@Bean
public Hibernate5Module hibernate5Module() {
return new Hibernate5Module();
} /*
* Jackson Afterburner module to speed up serialization/deserialization.
*/
@Bean
public AfterburnerModule afterburnerModule() {
return new AfterburnerModule();
} /*
* Module for serialization/deserialization of RFC7807 Problem.
*/
@Bean
ProblemModule problemModule() {
return new ProblemModule();
} /*
* Module for serialization/deserialization of ConstraintViolationProblem.
*/
@Bean
ConstraintViolationProblemModule constraintViolationProblemModule() {
return new ConstraintViolationProblemModule();
} }
package com.mycompany.myapp.utils; import java.text.ParseException;
import java.time.Instant;
import java.util.Date; import javax.validation.constraints.NotNull; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat; /**
* @author xuzhipeng
* @date 2018-11-22 13:51:05
* @since 1.0
*/
public class DateFormatUtil { public static final String SYMBOL_DOT = "\\."; public static final String DATE_REGEX_YYYYMM = "^\\d{4}-\\d{1,2}$";//日期正则yyyy-MM
public static final String DATE_REGEX_YYYYMMDD = "^\\d{4}-\\d{1,2}-\\d{1,2}$";//日期正则yyyy-MM-dd
public static final String DATE_REGEX_YYYYMMDDHHMM = "^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}$";//日期正则yyyy-MM-dd hh:mm
public static final String DATE_REGEX_YYYYMMDDHHMMSS = "^\\d{4}-\\d{1,2}-\\d{1,2} {1}\\d{1,2}:\\d{1,2}:\\d{1,2}$";//日期正则yyyy-MM-dd hh:mm:ss
public static final String DATE_REGEX_SECOND_DOT_NANOSECOND = "^[0-9]{1,}\\.[0-9]{1,9}$";//Instant日期秒+纳秒
public static final String DATE_REGEX_YYYYMMDD_T_HHMMSS_Z = "^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}Z$";//日期正则yyyy-MM-dd'T'HH:mm:ssZ
public static final String DATE_REGEX_YYYYMMDD_T_HHMMSS_SSS_Z = "^\\d{4}-\\d{1,2}-\\d{1,2}T\\d{1,2}:\\d{1,2}:\\d{1,2}\\.\\d{1,3}Z$";//日期正则yyyy-MM-dd'T'HH:mm:ss.SSSZ // 以T分隔日期和时间,并带时区信息,符合ISO8601规范
public static final String PATTERN_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSZZ";
public static final String PATTERN_ISO_ON_SECOND = "yyyy-MM-dd'T'HH:mm:ssZZ";
public static final String PATTERN_ISO_ON_DATE = "yyyy-MM-dd";
public static final String PATTERN_ISO_ON_MONTH = "yyyy-MM"; // 以空格分隔日期和时间,不带时区信息
public static final String PATTERN_DEFAULT = "yyyy-MM-dd HH:mm:ss.SSS";
public static final String PATTERN_DEFAULT_ON_SECOND = "yyyy-MM-dd HH:mm:ss";
public static final String PATTERN_DEFAULT_ON_MINUTE = "yyyy-MM-dd HH:mm"; // 使用工厂方法FastDateFormat.getInstance(), 从缓存中获取实例 // 以T分隔日期和时间,并带时区信息,符合ISO8601规范
public static final FastDateFormat ISO_FORMAT = FastDateFormat.getInstance(PATTERN_ISO);
public static final FastDateFormat ISO_ON_SECOND_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_SECOND);
public static final FastDateFormat ISO_ON_DATE_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_DATE);
public static final FastDateFormat ISO_ON_MONTH_FORMAT = FastDateFormat.getInstance(PATTERN_ISO_ON_MONTH); // 以空格分隔日期和时间,不带时区信息
public static final FastDateFormat DEFAULT_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT);
public static final FastDateFormat DEFAULT_ON_SECOND_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT_ON_SECOND);
public static final FastDateFormat DEFAULT_ON_MINUTE_FORMAT = FastDateFormat.getInstance(PATTERN_DEFAULT_ON_MINUTE); /**
* 将日期格式的字符串转换成指定格式的日期
* @param pattern 日期格式
* @param dateString 日期字符串
* @return
* @throws ParseException
*/
public static Date pareDate(@NotNull String pattern, @NotNull String dateString) throws ParseException {
return FastDateFormat.getInstance(pattern).parse(dateString);
} /**
* 将日期格式的字符串根据正则转换成相应格式的日期
* @param dateString 日期字符串
* @return
* @throws ParseException
*/
public static Date pareDate(@NotNull String dateString) throws ParseException {
String source = dateString.trim();
if (StringUtils.isNotBlank(source)) {
if(source.matches(DATE_REGEX_YYYYMM)){
return ISO_ON_MONTH_FORMAT.parse(source);
}else if(source.matches(DATE_REGEX_YYYYMMDD)){
return ISO_ON_DATE_FORMAT.parse(source);
}else if(source.matches(DATE_REGEX_YYYYMMDDHHMM)){
return DEFAULT_ON_MINUTE_FORMAT.parse(source);
}else if(source.matches(DATE_REGEX_YYYYMMDDHHMMSS)){
return DEFAULT_ON_SECOND_FORMAT.parse(source);
}else if(source.matches(DATE_REGEX_YYYYMMDD_T_HHMMSS_Z)){
return ISO_ON_SECOND_FORMAT.parse(source);
}else if(source.matches(DATE_REGEX_YYYYMMDD_T_HHMMSS_SSS_Z)){
return ISO_FORMAT.parse(source);
}else if(source.matches(DATE_REGEX_SECOND_DOT_NANOSECOND)){
String[] split = source.split(SYMBOL_DOT);
return Date.from(Instant.ofEpochSecond(Long.parseLong(split[0]), Long.parseLong(split[1])));
}else {
throw new IllegalArgumentException("Invalid date value '" + source + "'");
}
}
return null;
} }
并在pom文件中添加以下依赖:
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
参考:
1.http://www.cnblogs.com/liwc/p/9621435.html;
2.https://my.oschina.net/MeiJianMing/blog/1859609;
3.https://blog.csdn.net/howinfun/article/details/79271404。
二:对get请求中的Instant类型
1.定义全局Instant日期类型转换器:
package com.mycompany.myapp.config; import java.text.ParseException;
import java.time.Instant;
import java.util.Date; import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component; import com.mycompany.myapp.utils.DateFormatUtil; /**
* @author xuzhipeng
* @date 2019-03-20 18:02:41
* @since 1.0
*/
@Component
public class InstantConverter implements Converter<String,Instant> { @Override
public Instant convert(String source) {
String dateString = source.trim();
if(StringUtils.isNotBlank(dateString)){
Date pareDate;
try {
pareDate = DateFormatUtil.pareDate(dateString);
if(null != pareDate){
return pareDate.toInstant();
}
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
} }
2.springboot2.0以上只配置全局转换器不生效,需要加以下代码:
package com.mycompany.myapp.config; import java.util.Set; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.stereotype.Component; /**
* @author xuzhipeng
* @date 2019-03-22 16:04:49
* @since 1.0
*/
@Component
public class SpringContextListener implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private Set<Converter<?, ?>> converters;
@Autowired
private ConversionService conversionService; @Override
public void onApplicationEvent(ContextRefreshedEvent event) {
GenericConversionService gcs = (GenericConversionService) conversionService;
for (Converter<?, ?> converter : converters) {
gcs.addConverter(converter);
}
}
}
参考:
1.https://github.com/spring-projects/spring-boot/issues/6222;
2.https://github.com/spring-projects/spring-framework/issues/11081;
3.https://blog.csdn.net/qq_31871785/article/details/72863289。
三:实体类中的Instant类型返回yyyy-MM-dd格式:
package com.mycompany.myapp.config; import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer; /**
* @author xuzhipeng
* @date 2019-03-26 14:36:44
* @since 1.0
*/
public class CustomInstantDateSerializer extends StdSerializer<Instant> { private static final long serialVersionUID = 1L; private static DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public CustomInstantDateSerializer() {
this(null);
} public CustomInstantDateSerializer(Class<Instant> t) {
super(t);
} @Override
public void serialize(Instant instant, JsonGenerator jsonGenerator, SerializerProvider provider)
throws IOException {
if (instant == null) {
return;
}
String jsonValue = format.format(instant.atZone(ZoneId.systemDefault()));
jsonGenerator.writeString(jsonValue);
}
}
public class Event {
public String name;
@JsonSerialize(using = CustomInstantDateSerializer.class)
public Instant eventDate;
}
参考:
1.https://www.baeldung.com/jackson-serialize-dates;
转自链接:https://www.jianshu.com/p/2908a2515e3e
SpringBoot对接收及返回Instant类型的处理(转)的更多相关文章
- BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题
BeginInvoke与EndInvoke方法解决多线程接收委托返回值问题 原文:http://www.sufeinet.com/thread-3707-1-1.html 大家可以先看看我上 ...
- ajax接收php返回得到一堆html代码
ajax接收php返回得到一堆html代码 一. 错误代码: <font size='1'><table class='xdebug-error xe-notice' di ...
- CXF2.7整合spring发布webservice,返回值类型是Map和List<Map>类型
在昨天研究了发布CXF发布webservice之后想着将以前的项目发布webservice接口,可是怎么也发布不起来,服务启动失败,原来是自己的接口有返回值类型是Map. 研究了一番之后,发现: we ...
- MyBatis中Mapper的返回值类型
insert.update.delete语句的返回值类型 对数据库执行修改操作时,数据库会返回受影响的行数. 在MyBatis(使用版本3.4.6,早期版本不支持)中insert.update.del ...
- c#数据库訪问返回值类型为SqlDataReader时使用using时注意的问题
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u010512579/article/details/24011761 在封装通用 SQLSERVER ...
- ajax——优化0126(增删改查:添加查看详情,返回结果类型为JSON型,在窗口显示)
效果: 鼠标点击查看详情时 数据库: 0126.php <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu ...
- ASP.NET调用存储过程并接收存储过程返回值
ASP.NET调用存储过程并接收存储过程返回值 2010-08-02 11:26:17| 分类: C#|字号 订阅 2010年02月27日 星期六 23:52 假设表结构Create T ...
- Ajax详解及使用Ajax时的返回值类型有哪些?
Ajax详解 Ajax = 异步 JavaScript 和 XML. Ajax 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,Ajax 可以使网页实现异步更新.这意味着可以在 ...
- java中的方法返回值使用泛型,实现灵活的返回值类型
痛点: 使用Mybatis框架的时候,想封装一个底层JDBC控制器,用于提供和Mybatis交互的增删改查接口(公用的接口),但由于公用的查询方法可能是用户自定义的任意一个和表对应的java ...
随机推荐
- python+pycharm+PyQt5 图形化界面安装教程
python图形化界面安装教程 配置环境变量 主目录 pip所在目录,及script目录 更新pip(可选) python -m pip install --upgrade pip ps:更新出错一般 ...
- HDU1285(拓扑排序裸题
..被多组测试坑了一波 #include<iostream> #include<vector> #include<queue> using namespace st ...
- spark算子篇-repartition and coalesce
我们知道 RDD 是分区的,但有时候我们需要重新设置分区数量,增大还是减少需要结合实际场景,还有可以通过设置 RDD 分区数来指定生成的文件的数量 重新分区有两种方法:repartition and ...
- Pytest+allure安装和框架搭建
接口自动化框架搭建 -- 公司系统自测使用,只跑核心业务流程 编辑中...... 1.安装Pytest pip install -U pytest 1.1Pycharm测试脚本运行 创建project ...
- Java面试知识点汇总
Java面试知识点汇总 置顶 2019年05月07日 15:36:18 温柔的谢世杰 阅读数 21623 文章标签: 面经java 更多 分类专栏: java 面试 Java面试知识汇总 版权声明 ...
- word、ppt转换为pdf
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 你不知道的css各类布局(五)之em布局、rem布局
em布局/rem布局 em和rem的区别 在了解弹性布局前我们需要先知道em和rem rem:font size of the root element,rem是相对于根元素<html>来 ...
- warning C4819 的解决方法
编译VC++程序的时候出现如下提示警告: warning C4819: The file contains a character that cannot be represented in the ...
- JPanel实现滚动条
之前一直用JScrollPane里面放一个JTextArea,就可以在文本框内实现滚动条. 但是最近做一个小demo,需要在JPanel中实现滚动条,就找了下资料,做好了,现在记录一下,防止以后再用到 ...
- flutter: Another exception was thrown: Navigator operation requested with a context that does not include a Navigator.
import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends State ...