【发布时间】:2015-07-22 18:12:37
【问题描述】:
我一直在尝试解决一个 Spring Boot 应用程序的复杂问题,希望有人能帮助我。我已经删除了项目的所有其他部分,并试图使其尽可能简单。如果您访问 localhost:8080,将出现一个带有两个文本框的表单,用于输入两个名称,以及一个提交按钮。第一个名称将存储在 Nominee 对象中,第二个名称将存储在 Submitter 对象中。当您单击提交时,它将对字段执行验证以确保它们都不为空。我将在下面发布代码并在最后解释我的问题。
Application.java
@SpringBootApplication
@EnableJms
@EnableWebMvc
public class Application {
public static void main(String[] args) throws Exception {
// Launch the application
SpringApplication.run(Application.class, args);
}
}
WebController.java
@Controller
public class WebController extends WebMvcConfigurerAdapter {
protected static final Logger LOG = LoggerFactory.getLogger(WebController.class);
@InitBinder("nominee")
protected void initNomineeBinder(WebDataBinder binder) {
binder.setValidator(new NomineeValidator());
}
@InitBinder("submitter")
protected void initSubmitterBinder(WebDataBinder binder) {
binder.setValidator(new SubmitterValidator());
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/success").setViewName("success");
}
@RequestMapping(value="/", method=RequestMethod.GET)
public String showForm(Model model) {
model.addAttribute("nominee", new Nominee());
model.addAttribute("submitter", new Submitter());
return "form";
}
@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@ModelAttribute(value="nominee") @Valid Nominee nominee,
@ModelAttribute(value="submitter") @Valid Submitter submitter,
BindingResult bindingResult, @Valid Model model) {
LOG.info("Nominee to string: " + nominee.toString());
LOG.info("Submitter to string: " + submitter.toString());
LOG.info("bindingResult to string: " + bindingResult.toString());
if (bindingResult.hasErrors()) {
return "form";
}
return "redirect:/success";
}
}
Nominee.java
import lombok.Data;
@Data
public class Nominee {
private String name;
}
NomineeValidatior.java
public class NomineeValidator implements Validator {
public boolean supports(Class clazz) {
return Nominee.class.equals(clazz);
}
public void validate(Object object, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, "name", "name", "This field is empty.");
}
}
Submitter.java
import lombok.Data;
@Data
public class Submitter {
private String sname;
}
SubmitterValidator.java
public class SubmitterValidator implements Validator {
public boolean supports(Class clazz) {
return Submitter.class.equals(clazz);
}
public void validate(Object object, Errors errors) {
ValidationUtils.rejectIfEmpty(errors, "sname", "sname", "This field is empty.");
}
}
form.html
<html>
<body>
<form role="form" th:action="@{/}" method="post">
<h2>Nominee details</h2>
<table>
<tr>
<td>Name:</td>
<td>
<input type="text" th:field="${nominee.name}"/>
</td>
<td><p th:if="${#fields.hasErrors('nominee.name')}" th:errors="${nominee.name}">Empty field</p></td>
</tr>
</table>
<h2>Your details</h2>
<table>
<tr>
<td>Your name:</td>
<td>
<input type="text" th:field="${submitter.sname}"/>
</td>
<td><p th:if="${#fields.hasErrors('submitter.sname')}" th:errors="${submitter.sname}">Empty field</p></td>
</tr>
</table>
<div>
<button type="submit">Submit nomination</button>
</div>
</form>
</body>
</html>
success.html
<html><body>Form successfully submitted.</body></html>
如果我将第一个文本字段留空(并填写或不填写第二个文本字段),屏幕上会显示一条错误消息:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback. Tue May 12 13:10:17 AEST 2015 There was an unexpected error (type=Bad Request, status=400). Validation failed for object='nominee'. Error count: 1
我不知道如何解决它,以便将第一个文本框留空不会导致白标签错误页面。如果我将第二个文本字段留空但填写第一个,它的行为完全正常,所以我不确定如果我反过来尝试它为什么会导致错误。任何解决此问题的帮助将不胜感激。
另外,您可能已经注意到我必须在 Nominee 和 Submitter 中使用 'name' 和 'sname' 作为我的变量,如果我将它们都设置为 'name' 则它不能正常工作。如果有任何方法可以编辑它以便他们都可以使用“名称”,我很想知道如何。
编辑:找到解决方案。 在 WebController 中,checkPersonInfo 需要为每个正在验证的对象提供单独的 BindingResult。 BindingResult 需要在方法参数中紧跟每个@Valid 对象。
所以,在 WebController.java 中,这个:
@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@ModelAttribute(value="nominee") @Valid Nominee nominee,
@ModelAttribute(value="submitter") @Valid Submitter submitter,
BindingResult bindingResult, @Valid Model model) {
LOG.info("Nominee to string: " + nominee.toString());
LOG.info("Submitter to string: " + submitter.toString());
LOG.info("bindingResult to string: " + bindingResult.toString());
if (bindingResult.hasErrors()) {
return "form";
}
return "redirect:/success";
}
需要变成这样:
@RequestMapping(value="/", method=RequestMethod.POST)
public String checkPersonInfo(@ModelAttribute(value="nominee") @Valid Nominee nominee,
BindingResult bindingResultNominee,
@ModelAttribute(value="submitter") @Valid Submitter submitter,
BindingResult bindingResultSubmitter) {
LOG.info("Nominee to string: " + nominee.toString());
LOG.info("Submitter to string: " + submitter.toString());
if (bindingResultNominee.hasErrors() || bindingResultSubmitter.hasErrors()) {
return "form";
}
return "redirect:/success";
}
(模型对象已被删除,因为它从未在任何地方实际使用过,如果您需要使用 @Valid 对其进行验证,那么您将添加第三个 BindingResult 对象。)
【问题讨论】:
-
尝试将
org.springframework.web的日志记录打开到 DEBUG 以查看控制台是否显示任何有趣的内容。 -
只是想知道。为什么你要在这里进行服务器端验证而不是客户端验证(基于javascript)
-
没有真正的原因。第一次使用 Spring Boot,只是在玩弄它以自学它是如何工作的,看到它有自己的表单验证实现,并想尝试让它工作。
标签: java spring validation thymeleaf