表单验证返回白标签错误页面。

huangapple go评论94阅读模式
英文:

Form validation return white label error page

问题

我尝试使用Spring Boot 2.2和Thymeleaf进行表单验证,类似于文档示例(https://spring.io/guides/gs/validating-form-input/),但是当提交错误的值时,我得到一个白标签错误页面,而我应该在表单视图中绑定这些错误。如何修复这个问题?

我的控制器代码:

  1. @Controller
  2. public class TodoController {
  3. @RequestMapping(value = "/todo/create", method = RequestMethod.GET)
  4. public String tplTodoCreate(Model model) {
  5. TodoForm todoForm = new TodoForm();
  6. return "v-todo-create";
  7. }
  8. @RequestMapping(value = "/todo/create", method = RequestMethod.POST)
  9. public String tplTodoCreatePost(@ModelAttribute(name="formTodo") @Valid TodoForm todoForm, RedirectAttributes redirAttrs, BindingResult result) {
  10. if(result.hasErrors()) {
  11. return "v-todo-create";
  12. }
  13. todoRepository.save(todoForm);
  14. redirAttrs.addFlashAttribute("msgNotices", "Todo task created successfully.");
  15. return "redirect:/todos";
  16. }
  17. }

视图部分:

  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="tpl-default">
  3. <head>
  4. <title th:text="#{ctl-todo.create.meta.title}">Create New Todo</title>
  5. <link th:href="@{/css/todo/create.css}" rel="stylesheet" />
  6. </head>
  7. <body>
  8. <div id="wrapper" layout:fragment="content">
  9. <h2 class="page-header" th:text="#{ctl-todo.create.00001strid}">Add Todo</h2>
  10. <form name="todo" method="post" action="#" th:action="@{/todo/create}" th:object="${todoForm}" class="my-form-class">
  11. <div id="form">
  12. <div>
  13. <label for="form_name" class="required" th:text="#{ctl-todo.create.00002strid}">Name</label>
  14. <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></p>
  15. <input type="text" th:field="*{name}" id="form_name" name="name" min="1" max="30" required="required" class="form-control" style="margin-bottom:15px;" />
  16. </div>
  17. <div>
  18. <button type="submit" id="form_save" name="save" class="btn btn-primary" style="margin-bottom:15px;" th:text="#{ctl-todo.create.00013strid}">Create Todo</button>
  19. </div>
  20. </div>
  21. </form>
  22. <hr />
  23. <a class="btn btn-default" href="/todos"><span class="glyphicon glyphicon-floppy-remove"></span> <span th:text="#{ctl-todo.create.00014strid}">Back to todos list</span></a>
  24. </div>
  25. </body>
  26. </html>

堆栈跟踪如下:

  1. 2020-01-06 21:47:30.780 WARN 12140 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
  2. Field error in object 'formTodo' on field 'name': rejected value [a]; codes [Size.formTodo.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [formTodo.name,name]; arguments []; default message [name],30,2]; default message [size must be between 2 and 30]]
  3. White label error page is:
  4. Whitelabel Error Page
  5. This application has no explicit mapping for /error, so you are seeing this as a fallback.
  6. Tue Jan 07 10:08:07 GMT+01:00 2020
  7. There was an unexpected error (type=Bad Request, status=400).
  8. Validation failed for object='formTodo'. Error count: 1
  9. org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
  10. Field error in object 'formTodo' on field 'name': rejected value [a]; codes [Size.formTodo.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [formTodo.name,name]; arguments []; default message [name],30,2]; default message [size must be between 2 and 30]

通常情况下,name字段的min属性设置为1,但TodoForm实体具有min=2和max=30的Size约束。当我尝试提交只有一个字符的值时,会检测到正确的错误,但它返回的是白标签页面,而不是带有错误的视图。

编辑: 问题已解决。问题出现在tplTodoCreatePost()方法的参数顺序和@ModelAttribute(name="formTodo")上。方法签名已修改为 public String tplTodoCreatePost(@Valid TodoForm todoForm, BindingResult result, RedirectAttributes redirAttrs)

英文:

I tried to do a form validation using spring boot 2.2 and thymeleaf like the documentation example (https://spring.io/guides/gs/validating-form-input/) but I have a white label error page when wrong value are submitted when I should have a binding of these errors in my form view. How to fix that ?

My controller action code:

  1. @Controller
  2. public class TodoController {
  3. @RequestMapping(value = &quot;/todo/create&quot;, method = RequestMethod.GET)
  4. public String tplTodoCreate(Model model) {
  5. TodoForm todoForm = new TodoForm();
  6. return &quot;v-todo-create&quot;;
  7. }
  8. @RequestMapping(value = &quot;/todo/create&quot;, method = RequestMethod.POST)
  9. public String tplTodoCreatePost(@ModelAttribute(name=&quot;formTodo&quot;) @Valid TodoForm todoForm, RedirectAttributes redirAttrs, BindingResult result) {
  10. if(result.hasErrors()) {
  11. return &quot;v-todo-create&quot;;
  12. }
  13. todoRepository.save(todoForm);
  14. redirAttrs.addFlashAttribute(&quot;msgNotices&quot;, &quot;Todo task created successfuly.&quot;);
  15. return &quot;redirect:/todos&quot;;
  16. }
  17. }

and the view:

  1. &lt;!DOCTYPE html&gt;
  2. &lt;html xmlns:th=&quot;http://www.thymeleaf.org&quot; xmlns:layout=&quot;http://www.ultraq.net.nz/thymeleaf/layout&quot; layout:decorator=&quot;tpl-default&quot;&gt;
  3. &lt;head&gt;
  4. &lt;title th:text=&quot;#{ctl-todo.create.meta.title}&quot;&gt;Create New Todo&lt;/title&gt;
  5. &lt;link th:href=&quot;@{/css/todo/create.css}&quot; rel=&quot;stylesheet&quot; /&gt;
  6. &lt;/head&gt;
  7. &lt;body&gt;
  8. &lt;div id=&quot;wrapper&quot; layout:fragment=&quot;content&quot;&gt;
  9. &lt;h2 class=&quot;page-header&quot; th:text=&quot;#{ctl-todo.create.00001strid}&quot;&gt;Add Todo&lt;/h2&gt;
  10. &lt;form name=&quot;todo&quot; method=&quot;post&quot; action=&quot;#&quot; th:action=&quot;@{/todo/create}&quot; th:object=&quot;${todoForm}&quot; class=&quot;my-form-class&quot;&gt;
  11. &lt;div id=&quot;form&quot;&gt;
  12. &lt;div&gt;
  13. &lt;label for=&quot;form_name&quot; class=&quot;required&quot; th:text=&quot;#{ctl-todo.create.00002strid}&quot;&gt;Name&lt;/label&gt;
  14. &lt;p th:if=&quot;${#fields.hasErrors(&#39;name&#39;)}&quot; th:errors=&quot;*{name}&quot;&gt;&lt;/p&gt;
  15. &lt;input type=&quot;text&quot; th:field=&quot;*{name}&quot; id=&quot;form_name&quot; name=&quot;name&quot; min=&quot;1&quot; max=&quot;30&quot; required=&quot;required&quot; class=&quot;form-control&quot; style=&quot;margin-bottom:15px;&quot; /&gt;
  16. &lt;/div&gt;
  17. &lt;div&gt;
  18. &lt;button type=&quot;submit&quot; id=&quot;form_save&quot; name=&quot;save&quot; class=&quot;btn btn-primary&quot; style=&quot;margin-bottom:15px;&quot; th:text=&quot;#{ctl-todo.create.00013strid}&quot;&gt;Create Todo&lt;/button&gt;
  19. &lt;/div&gt;
  20. &lt;/div&gt;
  21. &lt;/form&gt;
  22. &lt;hr /&gt;
  23. &lt;a class=&quot;btn btn-default&quot; href=&quot;/todos&quot;&gt;&lt;span class=&quot;glyphicon glyphicon-floppy-remove&quot;&gt;&lt;/span&gt; &lt;span th:text=&quot;#{ctl-todo.create.00014strid}&quot;&gt;Back to todos list&lt;/span&gt;&lt;/a&gt;
  24. &lt;/div&gt;
  25. &lt;/body&gt;
  26. &lt;/html&gt;

The stacktrace is:

  1. 2020-01-06 21:47:30.780 WARN 12140 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
  2. Field error in object &#39;formTodo&#39; on field &#39;name&#39;: rejected value [a]; codes [Size.formTodo.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [formTodo.name,name]; arguments []; default message [name],30,2]; default message [size must be between 2 and 30]]

Whiteblabel error page is:

  1. Whitelabel Error Page
  2. This application has no explicit mapping for /error, so you are seeing this as a fallback.
  3. Tue Jan 07 10:08:07 GMT+01:00 2020
  4. There was an unexpected error (type=Bad Request, status=400).
  5. Validation failed for object=&#39;formTodo&#39;. Error count: 1
  6. org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
  7. Field error in object &#39;formTodo&#39; on field &#39;name&#39;: rejected value [a]; codes [Size.formTodo.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [formTodo.name,name]; arguments []; default message [name],30,2]; default message [size must be between 2 and 30]
  8. at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:164)
  9. at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121)
  10. at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167)
  11. at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
  12. at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
  13. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
  14. at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
  15. at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
  16. at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
  17. at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
  18. at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
  19. at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
  20. at javax.servlet.http.HttpServlet.service(HttpServlet.java:660)
  21. at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
  22. at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
  23. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
  24. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  25. at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
  26. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  27. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  28. at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
  29. at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
  30. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
  31. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
  32. at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
  33. at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
  34. at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
  35. at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
  36. at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
  37. at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
  38. at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
  39. at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
  40. at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
  41. at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
  42. at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1591)
  43. at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
  44. at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
  45. at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
  46. at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
  47. at java.base/java.lang.Thread.run(Thread.java:830)

Typicaly the name field have min attribute equals to 1 but the TodoForm entity have a Size constraint with min=2 and max=30. When I test to submit a value with only one character, the good error is detected but that return the error as a white label page rather than the view with the error.

EDIT: Probleme solved. It's caused by the order of parameter into the tplTodoCreatePost() method and the @ModelAttribute(name="formTodo"). The method signature was modifed as public String tplTodoCreatePost(@Valid TodoForm todoForm, BindingResult result, RedirectAttributes redirAttrs)

答案1

得分: 1

我会尝试向模型添加一个参数。但是如果没有堆栈跟踪,很难进行故障排除。你能否请将堆栈跟踪附加到你的帖子中?此外,Controller 的其余部分,包括 GET 方法映射,可能对此有帮助。

编辑:

我认为问题在于 tplTodoCreatePost 方法参数的顺序。请尝试将 BindingResult 放在 Model 之前,如下所示:

  1. public String tplTodoCreatePost(@Valid TodoForm todoForm, BindingResult result, @ModelAttribute(name="formTodo") RedirectAttributes redirAttrs) {
  2. // 方法体
  3. }
英文:

I would try to add a parameter to the model. But it's quite diffcult to troubleshoot without a stack trace. Could you please attach it to your post? Also the rest of the Controller, with GET method mapping could be helpful here.

EDIT:

I think the problem is the order of the parameters of the tplTodoCreatePost method. Please try to move BindingResult before Model, as below:

  1. public String tplTodoCreatePost(@Valid TodoForm todoForm, BindingResult result, @ModelAttribute(name=&quot;formTodo&quot;), RedirectAttributes redirAttrs, ) {
  2. // method body
  3. }

答案2

得分: 1

以下是您要翻译的代码部分:

  1. For information, I have removed the @ModelAttribute(name = "formTodo") because the error isn't displayed when I use it.
  2. @RequestMapping(value = "/todo/create", method = RequestMethod.POST)
  3. public String tplTodoCreatePost(@Valid TodoForm todoForm, BindingResult result, RedirectAttributes redirAttrs) {
  4. if(result.hasErrors()) {
  5. return "v-todo-create";
  6. }
  7. todoRepository.save(todoForm);
  8. redirAttrs.addFlashAttribute("msgNotices", "Todo task created successfully.");
  9. return "redirect:/todos";
  10. }
英文:

For information, I have remove the @ModelAttribute(name = "formTodo") because the error isn't displayed when I use it.

  1. @RequestMapping(value = &quot;/todo/create&quot;, method = RequestMethod.POST)
  2. public String tplTodoCreatePost(@Valid TodoForm todoForm, BindingResult result, RedirectAttributes redirAttrs) {
  3. if(result.hasErrors()) {
  4. return &quot;v-todo-create&quot;;
  5. }
  6. todoRepository.save(todoForm);
  7. redirAttrs.addFlashAttribute(&quot;msgNotices&quot;, &quot;Todo task created successfuly.&quot;);
  8. return &quot;redirect:/todos&quot;;
  9. }

huangapple
  • 本文由 发表于 2020年1月6日 14:49:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/59607828.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定