2017-02-16 99 views
0

我在驗證表單時遇到了麻煩。應該注意空或空selectedDate和描述字段,但我發現下面的錯誤,而不是驗證消息我預計:在POST請求(Springboot)上驗證表單時出現問題

There was an unexpected error (type=Bad Request, status=400). 
Validation failed for object='requestModel'. Error count: 2 

表:

<form role="form" th:action="@{/request/save}" th:object="${requestModel}" method="post"> 

    <input type="checkbox" th:field="*{hasForced}" th:checked="${false}" style="display: none;"/> 
    <p><input id="description" class="descriptionField" type="text" th:field="*{description}" 
       placeholder="Please provide a reason for your request" 
       style="width: 500px; border-radius: 4px; padding: 11px 11px 11px 11px;"/></p> 
    <input id="embeddedDateField" class="dateField" placeholder="YYYY-MM-DD" type="text" th:field="*{selectedDate}" readonly 
      style="border-radius: 4px; background: #eefdff; text-align: center;"/><br> 
    <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/> 
    <div style="margin: 5px; width: 200px;"><input type="submit" value="Submit Request" 
                style="display: block;"></div> 
    <p th:if="${#fields.hasErrors('description')}" th:errors="*{description}">Description Error</p> 
    <p th:if="${#fields.hasErrors('selectedDate')}" th:errors="*{selectedDate}">Date Error</p> 

</form> 

實體:

public class RequestModel { 

    private Long requestId; 

    @NotNull 
    @Min(1) 
    private String selectedDate; 

    private RequestStatus requestStatus; 

    @NotNull 
    @Min(1) 
    private String description; 

    private Boolean hasForced; 

    public String getSelectedDate() { 
     return selectedDate; 
    } 

    public void setSelectedDate(String selectedDate) { 
     this.selectedDate = selectedDate; 
    } 

    public Long getRequestId() { 
     return requestId; 
    } 

    public void setRequestId(Long requestId) { 
     this.requestId = requestId; 
    } 

    public RequestStatus getRequestStatus() { 
     return requestStatus; 
    } 

    public void setRequestStatus(RequestStatus requestStatus) { 
     this.requestStatus = requestStatus; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

    public Boolean getHasForced() { 
     return hasForced; 
    } 

    public void setHasForced(Boolean hasForced) { 
     this.hasForced = hasForced; 
    } 
} 

堆棧跟蹤:

java.text.ParseException: Unparseable date: "" 
    at java.text.DateFormat.parse(DateFormat.java:366) 
    at com.test.controller.RequestController.saveRequest(RequestController.java:75) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:826) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:964) 
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:867) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:841) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:124) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349) 
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783) 
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798) 
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434) 
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
    at java.lang.Thread.run(Thread.java:745) 

我在下面,因爲當你按下提交不提供任何明顯的輸入的日期爲空或空的控制器得到的錯誤在該行formattedDate = formatter.parse(requestModel.getSelectedDate());。但是,這不是表單驗證應該啓動的地方嗎?它不應該重定向到錯誤頁面,而應該不立即刷新當前頁面並顯示我提供的警告,即<p th:if="${#fields.hasErrors('selectedDate')}" th:errors="*{selectedDate}">Date Error</p>

這裏是控制器:

@Controller 
@RequestMapping("/request") 
public class RequestController { 

     @RequestMapping(value = "/save", method = RequestMethod.POST) 
      String saveRequest(Principal principal, @ModelAttribute(value = "requestModel") @Valid RequestModel requestModel, RedirectAttributes redirectAttributes, BindingResult bindingResult) { 

       // Refresh the page if there are errors 
       if (bindingResult.hasErrors()) { 
        return "request"; 
       } 

       // Create New RequestDO Object 
       Users user = usersRepository.findOneByInitialName(principal.getName()); 

       // Format given date 
       Date formattedDate = null; 
       try { 
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); 
        formattedDate = formatter.parse(requestModel.getSelectedDate()); 

       } catch (ParseException e) { 
        e.printStackTrace(); 
        return "error"; 
       } 

       if(!requestModel.getHasForced() && !isFirstHO(user, formattedDate)){ 
        redirectAttributes.addFlashAttribute("requestModel", requestModel); 
        return "redirect:/forceRequest"; 
       } 

       RequestDO requestDOOb = new RequestDO(); 

       // Set UserId to RequestDO Field USER_ID 
       requestDOOb.setUsers(user); 

       // Set Additional RequestDO Fields 
    requestDOOb.setDescription(!StringUtils.isEmpty(requestModel.getDescription()) ? requestModel.getDescription() : "I would like to make a request."); 
       requestDOOb.setStatus(RequestStatus.PENDING); 
       requestDOOb.setRequestDate(formattedDate); 

       // Save RequestDO Object 
       RequestDO sentRequest = requestRepository.save(requestDOOb); 

       return "redirect:/requests"; 
      } 
} 

重要。最後注意:下面的兩個答案構成了我的問題的綜合答案。最初有一個異常阻止了對bindingResult塊的訪問。其次,POST請求中參數的順序非常重要。請參閱下面的內容。

回答

1

裏面的try catch塊,你需要做以下幾點:

 try { 
      SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); 
      formattedDate = formatter.parse(requestModel.getSelectedDate()); 
     } catch (ParseException e) { 
      e.printStackTrace(); 
      bindingResult.rejectValue("selectedDate", "Invalid Date"); 
      return "request"; 
     } 
+0

那麼肯定修復異常!但不幸的是,不是我的問題。現在我完全沒有錯誤或堆棧跟蹤,但我仍然重定向到錯誤頁面,並且出現了一個意外錯誤(type = Bad Request,status = 400)。 對象='requestModel'驗證失敗。錯誤計數:2''。我應該提到,即使這些字段不是空的,我也會得到這個結果。當我刪除所有驗證註釋時,表單已成功提交。我遵循這個指南:https://spring.io/guides/gs/validating-form-input/#initial – santafebound

+0

同樣在調試中,我可以看到我從來沒有進入''if(bindingResult.hasErrors()){ log .info(「存在綁定錯誤。」); 返回「請求」; }'' – santafebound

0

我改變了我的POST請求的消息簽名。顯然的@Valid@ModelAttributeBindingResult的順序是非常敏感:

@RequestMapping(value = "/save", method = RequestMethod.POST) 
    String saveRequest(Principal principal, @Valid @ModelAttribute(value = "requestModel") RequestModel requestModel, BindingResult bindingResult, RedirectAttributes redirectAttributes) { 

     if (bindingResult.hasErrors()) { 
      log.info("There are binding errors."); 
      return "send"; 
     } 
... 
}