问题还原

前端通过GET请求后端接口 参数如下

http://XXX/station/line/goods?to=lts&startTime=2022-10-17 00:00:00&endTime=2022-10-17 23:59:59&fs=11&ss=197,11,193&page=0

后端接收代码

 @GetMapping(value = {"/station/line/goods"})
    public WebAsyncTask<ResponseResult> stationSearch(SearchParamDTO searchParamDTO
            , Pageable pageRequest
            , SessionInfo sessionInfo) {

SearchParamDTO 实体对象

package com.cqbxzc.go.sale.goods.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import live.jialing.util.time.ClockUtil;
import lombok.*;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 检索条件
 *
 * @author baizt
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString(callSuper = true)
public class SearchParamDTO implements Serializable {

    /**
     * 商品供应商ID集合
     */
    private List<Long> ss;
    /**
     * 商品类目编码集合
     */
    private List<String> ds;
    /**
     * 线路名称或编码
     */
    private String line;
    /**
     * 线路编码
     */
    private String lc;
    /**
     * 线路名称
     */
    private String ln;
    /**
     * 线路ID
     */
    private Long l;
    /**
     * 班次号
     */
    private String lrc;
    /**
     * 班次ID
     */
    private Long lrd;
    /**
     * 微信小程序的appId
     */
    private String w;
    /**
     * 起点:名称或助记码
     */
    private String from;
    /**
     * 起点:班次经停站点ID
     */
    private Long fromId;
    /**
     * 起点:场站(商户)ID
     */
    private Long fs;
    /**
     * 起点:区/县级行政编码
     */
    private String fa;
    /**
     * 起点:乡镇/街道行政编码
     */
    private String ft;
    /**
     * 起点:经度
     */
    private Double fromLon;
    /**
     * 起点:纬度
     */
    private Double fromLat;
    /**
     * 终点:名称或助记码
     */
    private String to;
    /**
     * 终点:班次经停站点ID
     */
    private Long toId;
    /**
     * 终点:场站(商户)ID
     */
    private Long ts;
    /**
     * 终点:区/县级行政编码
     */
    private String ta;
    /**
     * 终点:乡镇/街道行政编码
     */
    private String tt;
    /**
     * 终点:经度
     */
    private Double toLon;
    /**
     * 终点:纬度
     */
    private Double toLat;
    /**
     * 发车时间:开始 2018-01-11 09:45:01
     */
    @DateTimeFormat(pattern = ClockUtil.LOCAL_DATE_TIME_FORMATTER_PATTERN)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = ClockUtil.LOCAL_DATE_TIME_FORMATTER_PATTERN, timezone = ClockUtil.DEFAULT_TIME_ZONE)
    private LocalDateTime startTime;
    /**
     * 发车时间:结束 2018-01-11 09:45:02
     */
    @DateTimeFormat(pattern = ClockUtil.LOCAL_DATE_TIME_FORMATTER_PATTERN)
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = ClockUtil.LOCAL_DATE_TIME_FORMATTER_PATTERN, timezone = ClockUtil.DEFAULT_TIME_ZONE)
    private LocalDateTime endTime;

}

调用结果

GET - /yesgs/station/line/goods
18:02:25.371 [http-nio-8081-exec-1] ERROR c.c.b.w.h.ControllerExceptionHandler - org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'searchParamDTO' on field 'endTime': rejected value [2022-10-17 23:59:59]; codes [methodInvocation.searchParamDTO.endTime,methodInvocation.endTime,methodInvocation.java.time.LocalDateTime,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [searchParamDTO.endTime,endTime]; arguments []; default message [endTime]]; default message [Property 'endTime' threw exception; nested exception is java.time.format.DateTimeParseException: Text '2022-10-17 23:59:59' could not be parsed, unparsed text found at index 10]
Field error in object 'searchParamDTO' on field 'startTime': rejected value [2022-10-17 00:00:00]; codes [methodInvocation.searchParamDTO.startTime,methodInvocation.startTime,methodInvocation.java.time.LocalDateTime,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [searchParamDTO.startTime,startTime]; arguments []; default message [startTime]]; default message [Property 'startTime' threw exception; nested exception is java.time.format.DateTimeParseException: Text '2022-10-17 00:00:00' could not be parsed, unparsed text found at index 10]
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 errors
Field error in object 'searchParamDTO' on field 'endTime': rejected value [2022-10-17 23:59:59]; codes [methodInvocation.searchParamDTO.endTime,methodInvocation.endTime,methodInvocation.java.time.LocalDateTime,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [searchParamDTO.endTime,endTime]; arguments []; default message [endTime]]; default message [Property 'endTime' threw exception; nested exception is java.time.format.DateTimeParseException: Text '2022-10-17 23:59:59' could not be parsed, unparsed text found at index 10]
Field error in object 'searchParamDTO' on field 'startTime': rejected value [2022-10-17 00:00:00]; codes [methodInvocation.searchParamDTO.startTime,methodInvocation.startTime,methodInvocation.java.time.LocalDateTime,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [searchParamDTO.startTime,startTime]; arguments []; default message [startTime]]; default message [Property 'startTime' threw exception; nested exception is java.time.format.DateTimeParseException: Text '2022-10-17 00:00:00' could not be parsed, unparsed text found at index 10]
	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:164)
	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:878)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
	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:626)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:126)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:118)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at com.cqbxzc.gateway.security.filter.JwtAuthenticationFilter.doFilterInternal(JwtAuthenticationFilter.java:106)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:158)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:92)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:92)
	at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:77)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
	at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at com.cqbxzc.boot.webmvc.context.filter.LogFilter.doFilterInternal(LogFilter.java:59)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	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.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:832)
18:02:25.482 [http-nio-8081-exec-1] INFO  c.c.g.s.RequestIdempotentInterceptor - Response . 耗时 248 毫秒

问题解决

通过百度找资料一直没有找到,没有办法只有更具断点调试springMvc源码
最终发现如果配置@InitBinde属性编辑器spring会自动取你配置的属性编辑器来解析对应类型的属性
PropertyEditor editor=this.customEditors.get(requiredType);
该方法存在于PropertyEditorRegistrySupport类中

	@Nullable
	private PropertyEditor getCustomEditor(@Nullable Class<?> requiredType) {
		if (requiredType == null || this.customEditors == null) {
			return null;
		}
		// Check directly registered editor for type.
		//在次方法获取的属性编辑器
		PropertyEditor editor = this.customEditors.get(requiredType);
		if (editor == null) {
			// Check cached editor for type, registered for superclass or interface.
			if (this.customEditorCache != null) {
				editor = this.customEditorCache.get(requiredType);
			}
			if (editor == null) {
				// Find editor for superclass or interface.
				for (Iterator<Class<?>> it = this.customEditors.keySet().iterator(); it.hasNext() && editor == null;) {
					Class<?> key = it.next();
					if (key.isAssignableFrom(requiredType)) {
						editor = this.customEditors.get(key);
						// Cache editor for search type, to avoid the overhead
						// of repeated assignable-from checks.
						if (this.customEditorCache == null) {
							this.customEditorCache = new HashMap<>();
						}
						this.customEditorCache.put(requiredType, editor);
					}
				}
			}
		}
		return editor;
	}

发现果然配置LocalDateTime属性解析器

     */
    @InitBinder
    protected void initBinder(WebDataBinder binder) {

        // Double
        binder.registerCustomEditor(Double.class, new CustomNumberEditor(Double.class, true));

        // Date
        SimpleDateFormat sdf = new SimpleDateFormat(ClockUtil.LOCAL_DATE_FORMATTER_PATTERN);
        // 这个的功能是不把1996-13-3 转换为1997-1-3
        // 这样输入1996-2-31这样的数据也会验证出来错误的,但是前提是要设置Lenient为false
        sdf.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));

        // LocalDateTime 等
         binder.registerCustomEditor(LocalDateTime.class, new LocaleDateTimeEditor(LocalDateTime.class, "yyyy-MM-dd", true));
         binder.registerCustomEditor(LocalDate.class, new LocaleDateTimeEditor(LocalDate.class, "yyyy-MM-dd", true));
         binder.registerCustomEditor(LocalTime.class, new LocaleDateTimeEditor(LocalTime.class, "HH:mm:ss", true));
    }

最后去掉了 binder.registerCustomEditor(LocalDateTime.class, new LocaleDateTimeEditor(LocalDateTime.class, “yyyy-MM-dd”, true));
问题解决

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐