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 ...
随机推荐
- 23.安装php和echarts进行结合展示图表
数据展示 http://echarts.baidu.com/index.html 是一个图像展示 可以到官方实例中选择各种图 通过下载例子 新建echartdome.php <!DOCTYPE ...
- 【深入浅出-JVM】(2):原码、反码、补码
计算机中有补码表示 0 0 为正数 原码 00000000 00000000 00000000 00000000 反码 00000000 00000000 00000000 00000000 正数反码 ...
- Netty怎么切换三种I/O模式和源码解释
参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! 三种I/O模式 BIO:Block I/O,即同步并阻塞的IO:BI ...
- HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并)
layout: post title: HDU-6704 K-th occurrence (后缀自动机father树上倍增建权值线段树合并) author: "luowentaoaa&quo ...
- Linux下通过ssh上传下载文件
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/jun8148/article/deta ...
- luffy前台配置
目录 axios前后台交互 cokies操作 element-ui页面组件框架 bootstrap页面组件框架 前端主页 图片准备 页头组件:components/Header.vue 轮播图组件:c ...
- spark算子篇-repartition and coalesce
我们知道 RDD 是分区的,但有时候我们需要重新设置分区数量,增大还是减少需要结合实际场景,还有可以通过设置 RDD 分区数来指定生成的文件的数量 重新分区有两种方法:repartition and ...
- JDK1.8新特性(二):Collectors收集器类
一. 什么是Collectors? Java 8 API添加了一个新的抽象称为流Stream,我们借助Stream API可以很方便的操作流对象. Stream中有两个方法collect和collec ...
- ssh无密登录_集群分发脚本xsync
1.ssh免密登录 ssh ip地址 [root@192 ~]# ssh 192.168.1.102 root@192.168.1.102's password: Last login: Mon Fe ...
- 怎样理解 MVVM ( Model-View-ViewModel ) ?
MVVM 的 产生 / 实现 / 发展 可以写一篇很长的博客了, 这里仅写一下个人对 MVVM的一些肤浅的认识. 1. 在 没有 MVVM 之前, 前端可以说是 jQuery一把梭 , jQuery ...