spring boot 2.2.3对 jdk 8 的时间处理

用例一_get.post请求接口LocalDateTime 参数

    @GetMapping("get/localDateTime")
    @ApiOperation(value = "get 请求 localDateTime 作为参数赋值", produces = "application/json")
    public BaseResponse get(LocalDateTime localDateTime) {
        return BaseResponse.success(LocalDateTimeUtils.format(localDateTime, DateFromatEnum.YYYY_MM_DD_HH_MM_SS));
    }

    @GetMapping("get/localDateTime/2")
    @ApiOperation(value = "get 请求 localDateTime 作为参数赋值", produces = "application/json")
    public BaseResponse getRequestParam(@RequestParam LocalDateTime localDateTime) {
        return BaseResponse.success(LocalDateTimeUtils.format(localDateTime, DateFromatEnum.YYYY_MM_DD_HH_MM_SS));
    }

    @PostMapping("post/localDateTime")
    @ApiOperation(value = "post 请求 localDateTime 作为参数赋值", produces = "application/json")
    public BaseResponse post(LocalDateTime localDateTime) {
        return BaseResponse.success(LocalDateTimeUtils.format(localDateTime, DateFromatEnum.YYYY_MM_DD_HH_MM_SS));
    }

    @PostMapping("post/localDateTime/2")
    @ApiOperation(value = "post 请求 localDateTime 作为参数赋值", produces = "application/json")
    public BaseResponse postRequestParam(@RequestParam LocalDateTime localDateTime) {
        return BaseResponse.success(LocalDateTimeUtils.format(localDateTime, DateFromatEnum.YYYY_MM_DD_HH_MM_SS));
    }
  • 异常信息如下
org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime'; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDateTime] for value '2020-06-18 11:00:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2020-06-18 11:00:00]
	at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:133)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:763)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1631)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at brave.servlet.TracingFilter.doFilter(TracingFilter.java:67)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.boot.web.servlet.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:54)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at cn.zhangfusheng.base.server.fileter.ProjectBaseFilter.doFilter(ProjectBaseFilter.java:55)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter.doFilter(ExceptionLoggingFilter.java:50)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at brave.servlet.TracingFilter.doFilter(TracingFilter.java:84)
	at org.springframework.cloud.sleuth.instrument.web.LazyTracingFilter.doFilter(TraceWebServletAutoConfiguration.java:138)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:549)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:602)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1610)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1363)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:489)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1278)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.Server.handle(Server.java:500)
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
	at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:375)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.time.LocalDateTime] for value '2020-06-18 11:00:00'; nested exception is java.lang.IllegalArgumentException: Parse attempt failed for value [2020-06-18 11:00:00]
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47)
	at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191)
	at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:129)
	at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73)
	at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:53)
	at org.springframework.validation.DataBinder.convertIfNecessary(DataBinder.java:693)
	at org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver.resolveArgument(AbstractNamedValueMethodArgumentResolver.java:125)
	... 73 common frames omitted
Caused by: java.lang.IllegalArgumentException: Parse attempt failed for value [2020-06-18 11:00:00]
	at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:223)
	at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41)
	... 79 common frames omitted
Caused by: java.time.format.DateTimeParseException: Text '2020-06-18 11:00:00' could not be parsed at index 2
	at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
	at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
	at java.time.LocalDateTime.parse(LocalDateTime.java:492)
	at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:75)
	at org.springframework.format.datetime.standard.TemporalAccessorParser.parse(TemporalAccessorParser.java:46)
	at org.springframework.format.support.FormattingConversionService$ParserConverter.convert(FormattingConversionService.java:217)
	... 80 common frames omitted
  • 解决方案__添加类型转换器__code
自定义类型转换器
package cn.zhangfusheng.base.server.converter;

import cn.zhangfusheng.util.base.date.LocalDateTimeUtils; // 自定义的时间格式化工具
import cn.zhangfusheng.util.base.exception.GlobalException; // 自定义的全局异常
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;

import java.time.LocalDateTime;

/**
 * @description : 自定义类型转换器
 * @author: fusheng.zhang
 * @date: 2019/5/17 11:10
 */
@Slf4j
public class TypeConverter {
  
    /**
     * @description : LocalDateTime 类型转换器
     * @author: fusheng.zhang
     * @date: 2019/5/17 10:54
     */
    public static class LocalDateTimeConvert implements Converter {

        @Override
        public LocalDateTime convert(String source) {
            if (StringUtils.isBlank(source)) {
                throw new NullPointerException();
            }
            return LocalDateTimeUtils.parseMatches(source);
        }
    }
}
添加转换器
package cn.zhangfusheng.base.server.config;

import cn.zhangfusheng.base.server.converter.TypeConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @description :
 * @author: fusheng.zhang
 * @date: 2019/5/17 11:33
 */
@Slf4j
@Configuration
public class TypeConfig implements WebMvcConfigurer {

    /**
     * 添加类型转换器
     * @param registry
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        log.debug("加载处理时间请求参数的Convert");
        registry.addConverter(new TypeConverter.LocalDateTimeConvert());
    }
}
  • 测试
    spring boot 2.2.3对 jdk 8 的时间处理_第1张图片

用例二_post _RequestBody 实体中接收LocalDateTime类型的参数

  • 实体
package cn.zhangfusheng.user.server.controller;

import java.time.LocalDateTime;

public class LocalDateTimeModel {

    private LocalDateTime createTime;

    private LocalDateTime updateTime;

    public LocalDateTime getCreateTime() {
        return createTime;
    }

    public void setCreateTime(LocalDateTime createTime) {
        this.createTime = createTime;
    }

    public LocalDateTime getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(LocalDateTime updateTime) {
        this.updateTime = updateTime;
    }
}
  • 测试接口
    @PostMapping("post/model/localDateTime")
    @ApiOperation(value = "post 请求 localDateTime 作为参数赋值", produces = "application/json")
    public BaseResponse<Object> postRequestBody(@RequestBody LocalDateTimeModel model) {
        return BaseResponse.success(model);
    }
  • 测试1

前端传递如下请求参数:
{ “createTime”: “2020-06-18T03:50:06.024Z”, “updateTime”: “2020-06-18T03:50:06.024Z”}
接口可以正常接收到参数

  • 测试1结果
    spring boot 2.2.3对 jdk 8 的时间处理_第2张图片
  • 测试二

传递如下格式的参数
{ “createTime”: “2020-06-18 03:55:02”, “updateTime”: “2020-06-18 03:55:02”}
发生如下异常

 at [Source: (PushbackInputStream); line: 2, column: 17] (through reference chain: cn.zhangfusheng.user.server.controller.LocalDateTimeModel["createTime"])
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-06-18 03:55:02": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2020-06-18 03:55:02' could not be parsed at index 10; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-06-18 03:55:02": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2020-06-18 03:55:02' could not be parsed at index 10
 at [Source: (PushbackInputStream); line: 2, column: 17] (through reference chain: cn.zhangfusheng.user.server.controller.LocalDateTimeModel["createTime"])
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:245)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:227)
	at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodArgumentResolver.readWithMessageConverters(AbstractMessageConverterMethodArgumentResolver.java:205)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.readWithMessageConverters(RequestResponseBodyMethodProcessor.java:158)
	at org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor.resolveArgument(RequestResponseBodyMethodProcessor.java:131)
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:523)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:763)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1631)
	at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at brave.servlet.TracingFilter.doFilter(TracingFilter.java:67)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.boot.web.servlet.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:54)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at cn.zhangfusheng.base.server.fileter.ProjectBaseFilter.doFilter(ProjectBaseFilter.java:55)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.cloud.sleuth.instrument.web.ExceptionLoggingFilter.doFilter(ExceptionLoggingFilter.java:50)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at brave.servlet.TracingFilter.doFilter(TracingFilter.java:84)
	at org.springframework.cloud.sleuth.instrument.web.LazyTracingFilter.doFilter(TraceWebServletAutoConfiguration.java:138)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1618)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:549)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:602)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1610)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1363)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:489)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1580)
	at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1278)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
	at org.eclipse.jetty.server.Server.handle(Server.java:500)
	at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:383)
	at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:547)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:375)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:273)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
	at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:135)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:806)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
	at java.lang.Thread.run(Thread.java:748)
Caused by: com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-06-18 03:55:02": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2020-06-18 03:55:02' could not be parsed at index 10
 at [Source: (PushbackInputStream); line: 2, column: 17] (through reference chain: cn.zhangfusheng.user.server.controller.LocalDateTimeModel["createTime"])
	at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
	at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1698)
	at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:947)
	at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleDateTimeException(JSR310DeserializerBase.java:129)
	at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:102)
	at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:39)
	at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:371)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4482)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3487)
	at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:239)
	... 76 common frames omitted
Caused by: java.time.format.DateTimeParseException: Text '2020-06-18 03:55:02' could not be parsed at index 10
	at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
	at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
	at java.time.LocalDateTime.parse(LocalDateTime.java:492)
	at com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer.deserialize(LocalDateTimeDeserializer.java:100)
	... 83 common frames omitted

  • 全局解决_code_也可以在字段上添加注解
package cn.zhangfusheng.base.server.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * @description :
 * @author: fusheng.zhang
 * @date: 2019/5/17 11:33
 */
@Slf4j
@Configuration
public class TypeConfig {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }
}
  • 测试结果
    spring boot 2.2.3对 jdk 8 的时间处理_第3张图片

用例三_响应给前端的数据时间格式化

  • 在用例二中可以看到返回给前端的数据格式如下
{
  "result": 200,
  "msg": null,
  "data": {
    "createTime": [
      2020,
      6,
      18,
      3,
      55,
      2
    ],
    "updateTime": [
      2020,
      6,
      18,
      3,
      55,
      2
    ]
  }
}
  • 返回给前端 yyyy-MM-dd HH:mm:ss 格式的数据 全局配置
    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // 序列化
        javaTimeModule.addSerializer(LocalDateTime.class,new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }

整理全部代码如下

package cn.zhangfusheng.util.base.date.enumeration;

import java.time.format.DateTimeFormatter;

/**
 * @Description 时间类型常量
 * @author fusheng.zhang
 * @create 2019-08-26 17:11:00
 */
public enum DateFromatEnum {
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    YYYY("yyyy"),
    YYYY_MM("yyyy-MM"),
    YYYY_MM_1("yyyy/MM"),
    YYYY_MM_2("yyyyMM"),
    YYYY_MM_DD("yyyy-MM-dd"),
    YYYY_MM_DD_1("yyyy/MM/dd"),
    YYYY_MM_DD_2("yyyyMMdd"),
    HH_MM_SS("HH:mm:ss"),
    HH_MM_SS_1("HH/mm/ss"),
    HH_MM_SS_2("HHmmss"),
    YYYY_MM_DD_HH("yyyy-MM-dd HH"),
    YYYY_MM_DD_HH_1("yyyy/MM/dd HH"),
    YYYY_MM_DD_HH_2("yyyyMMdd HH"),
    YYYY_MM_DD_HH_MM("yyyy-MM-dd HH:mm"),
    YYYY_MM_DD_HH_MM_1("yyyy/MM/dd HH/mm"),
    YYYY_MM_DD_HH_MM_2("yyyyMMdd HHmm"),
    YYYY_MM_DD_HH_MM_SS("yyyy-MM-dd HH:mm:ss"),
    YYYY_MM_DD_HH_MM_SS_1("yyyy/MM/dd HH/mm/ss"),
    YYYY_MM_DD_HH_MM_SS_2("yyyyMMdd HHmmss"),
    ;


    private transient DateTimeFormatter formatter;

    DateFromatEnum(String pattern) {
        formatter = DateTimeFormatter.ofPattern(pattern);
    }

    public DateTimeFormatter getFormatter() {
        return formatter;
    }

    public void setFormatter(DateTimeFormatter formatter) {
        this.formatter = formatter;
    }
}

package cn.zhangfusheng.util.base.date.enumeration;

import java.time.temporal.ChronoUnit;

/**
 * @Description
 * @author fusheng.zhang
 * @create 2019-08-29 17:16:00
 */
public enum DateAddEnum {
    /**
     * 年
     */
    YEARS("YEARS"),
    MONTHS("MONTHS"),
    DAYS("DAYS"),
    HOURS("HOURS"),
    MINUTES("MINUTES"),
    SECONDS("SECONDS"),
    WEEKS("WEEKS"),
    ;

    private transient ChronoUnit chronoUnit;

    DateAddEnum(String pattern) {
        chronoUnit = ChronoUnit.valueOf(pattern);
    }

    public ChronoUnit getChronoUnit() {
        return chronoUnit;
    }

    public void setChronoUnit(ChronoUnit chronoUnit) {
        this.chronoUnit = chronoUnit;
    }
}

package cn.zhangfusheng.util.base.date;

import cn.zhangfusheng.util.base.date.enumeration.DateAddEnum;
import cn.zhangfusheng.util.base.date.enumeration.DateFromatEnum;

import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

/**
 * 是否需要添加 synchronized 关键字
 * @author fusheng.zhang
 */
public final class LocalDateTimeUtils {

    private final static String[] WEEKS = {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"};

    /**
     * 获取当前时间
     * @return
     */
    public static String nowTime(DateFromatEnum dateFromatEnum) {
        return LocalDateTimeUtils.format(LocalDateTime.now(), dateFromatEnum);
    }

    /**
     * Date转LocalDateTime
     * @param date Date对象
     * @return
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    }

    /**
     * LocalDateTime转换为Date
     * @param dateTime LocalDateTime对象
     * @return
     */
    public static Date localDateTimeToDate(LocalDateTime dateTime) {
        return Date.from(dateTime.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 格式化时间
     * @param localDateTime  LocalDateTime对象
     * @param dateFromatEnum 格式化表达式
     * @return
     */
    public static String format(LocalDateTime localDateTime, DateFromatEnum dateFromatEnum) {
        return localDateTime.format(dateFromatEnum.getFormatter());
    }

    /**
     * 反序列化
     * 注意
     * @param dateTime       字符串时间
     * @param dateFromatEnum 格式化方式
     * @return
     */
    public static LocalDateTime parse(String dateTime, DateFromatEnum dateFromatEnum) {
        if (DateFromatEnum.YYYY.equals(dateFromatEnum)) {
            return Year.parse(dateTime, dateFromatEnum.getFormatter()).atDay(1).atStartOfDay();
        } else if (DateFromatEnum.YYYY_MM.equals(dateFromatEnum) || DateFromatEnum.YYYY_MM_1.equals(dateFromatEnum) || DateFromatEnum.YYYY_MM_2.equals(dateFromatEnum)) {
            return YearMonth.parse(dateTime, dateFromatEnum.getFormatter()).atDay(1).atStartOfDay();
        } else if (DateFromatEnum.YYYY_MM_DD.equals(dateFromatEnum) || DateFromatEnum.YYYY_MM_DD_1.equals(dateFromatEnum) || DateFromatEnum.YYYY_MM_DD_2.equals(dateFromatEnum)) {
            return LocalDate.parse(dateTime, dateFromatEnum.getFormatter()).atStartOfDay();
        } else {
            return LocalDateTime.parse(dateTime, dateFromatEnum.getFormatter());
        }
    }

    /**
     * 通过匹配正则表达式反序列化时间
     * @param dateTime
     * @return
     */
    public static LocalDateTime parseMatches(String dateTime) {
        if (dateTime.matches("^\\d{4}")) {
            return parse(dateTime, DateFromatEnum.YYYY);
        } else if (dateTime.matches("^\\d{4}-\\d{1,2}$")) {
            return parse(dateTime, DateFromatEnum.YYYY_MM);
        } else if (dateTime.matches("^\\d{4}-\\d{1,2}-\\d{1,2}$")) {
            return parse(dateTime, DateFromatEnum.YYYY_MM_DD);
        } else {
            return parse(dateTime, DateFromatEnum.YYYY_MM_DD_HH_MM_SS);
        }
    }

    /**
     * 获取当天的开始时间
     * @param localDateTime 时间
     * @return
     */
    public static LocalDateTime getStartTime(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate().atStartOfDay();
    }

    /**
     * 日期计算
     * 根据时间单位计算
     * @param localDateTime 时间
     * @param amountToAdd   增值 + -
     * @param dateAddEnum   时间单位 具体参考枚举 ChronoUnit
     * @return
     */
    public static LocalDateTime plus(LocalDateTime localDateTime, long amountToAdd, DateAddEnum dateAddEnum) {
        return localDateTime.plus(amountToAdd, dateAddEnum.getChronoUnit());
    }

    /**
     * 获取周几
     * @param localDateTime
     * @return
     */
    public static String getWeek(LocalDateTime localDateTime) {
        return WEEKS[localDateTime.getDayOfWeek().getValue()];
    }

    /**
     * 获取本月有多少天
     * @param localDateTime
     * @return
     */
    public static int getMonthDays(LocalDateTime localDateTime) {
        return localDateTime.getMonth().length(localDateTime.toLocalDate().isLeapYear());
    }

    /**
     * 判断今年是否是闰年
     * @param localDateTime
     * @return
     */
    public static boolean isLeapYear(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate().isLeapYear();
    }

    /**
     * 获取某天的开始时间00:00:00
     * @param dateTime 某天时间
     * @return
     */
    public static LocalDateTime getDayStart(LocalDateTime dateTime) {
        return dateTime.with(LocalTime.MIN);
    }

    /**
     * 获取某天的结束时间23:59:59
     * @param dateTime
     * @return
     */
    public static LocalDateTime getDayEnd(LocalDateTime dateTime) {
        return dateTime.with(LocalTime.MAX);
    }

    /**
     * 获取某月第一天的00:00:00
     * @param dateTime LocalDateTime对象
     * @return
     */
    public static LocalDateTime getFirstDayOfMonth(LocalDateTime dateTime) {
        return dateTime.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
    }

    /**
     * 获取某月最后一天的23:59:59
     * @param dateTime LocalDateTime对象
     * @return
     */
    public static LocalDateTime getLastDayOfMonth(LocalDateTime dateTime) {
        return dateTime.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
    }

    /**
     * 获取毫秒时间戳
     * @param localDateTime
     * @return
     */
    public static long getMilli(LocalDateTime localDateTime) {
        return localDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli();
    }

    /**
     * 获取周一
     * @param localDate
     * @return
     */
    public static LocalDate getFirtWeek(LocalDate localDate) {
        return localDate.with(DayOfWeek.MONDAY);
    }

    /**
     * 获取周一
     * @param localDate
     * @return
     */
    public static LocalDateTime getFirtWeek(LocalDateTime localDate) {
        return localDate.with(DayOfWeek.MONDAY);
    }

    /**
     * 获取一周的周日
     * @param localDate
     * @return
     */
    public static LocalDate getEndWeek(LocalDate localDate) {
        return localDate.with(DayOfWeek.SUNDAY);
    }

    /**
     * 获取一周的周日
     * @param localDateTime
     * @return
     */
    public static LocalDateTime getEndWeek(LocalDateTime localDateTime) {
        return localDateTime.with(DayOfWeek.SUNDAY);
    }

    /**
     * 获取时间戳
     * @return
     */
    public static Long getMillis() {
        return System.currentTimeMillis();
    }

}
package cn.zhangfusheng.base.server.converter;

import cn.zhangfusheng.util.base.date.LocalDateTimeUtils;
import cn.zhangfusheng.util.base.exception.GlobalException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.convert.converter.Converter;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @description : 自定义类型转换器
 * @author: fusheng.zhang
 * @date: 2019/5/17 11:10
 */
@Slf4j
public class TypeConverter {
    /**
     * Date 类型转换器
     *
     * @author zhanghang
     * @date 2018/1/11
     */
    public static class DateConverter implements Converter<String, Date> {

        @Override
        public Date convert(String source) {
            if (StringUtils.isBlank(source)) {
                throw new NullPointerException();
            }
            return LocalDateTimeUtils.localDateTimeToDate(LocalDateTimeUtils.parseMatches(source));
        }
    }

    /**
     * @description : LocalDateTime 类型转换器
     * @author: fusheng.zhang
     * @date: 2019/5/17 10:54
     */
    public static class LocalDateTimeConvert implements Converter<String, LocalDateTime> {

        @Override
        public LocalDateTime convert(String source) {
            if (StringUtils.isBlank(source)) {
                throw new NullPointerException();
            }
            return LocalDateTimeUtils.parseMatches(source);
        }
    }
}

package cn.zhangfusheng.base.server.config;

import cn.zhangfusheng.base.server.converter.TypeConverter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

/**
 * @description :
 * @author: fusheng.zhang
 * @date: 2019/5/17 11:33
 */
@Slf4j
@Configuration
public class TypeConfig implements WebMvcConfigurer {

    @Bean
    public ObjectMapper objectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // 序列化
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        // 反序列化
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
        javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
        return objectMapper;
    }


    /**
     * 添加类型转换器
     * @param registry
     */
    @Override
    public void addFormatters(FormatterRegistry registry) {
        log.debug("加载处理时间请求参数的Convert");
        registry.addConverter(new TypeConverter.DateConverter());
        registry.addConverter(new TypeConverter.LocalDateTimeConvert());
    }

}

你可能感兴趣的:(spring,boot,spring,boot,jdk8,LocalDateTime)