我在弄错我的表格时遇到了麻烦。它应该注意null或清空selectedDate和description字段,但我得到以下错误而不是我期望的验证消息:
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请求中参数的顺序非常重要。请看下面两个。
答案 0 :(得分: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";
}
答案 1 :(得分:0)
我更改了POST请求的消息签名。显然,@Valid
,@ModelAttribute
和BindingResult
的顺序非常敏感:
@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";
}
...
}