У меня возникла сложная проблема с приложением Spring Boot, которое я пытался решить некоторое время, и я надеюсь, что кто-то может мне помочь. Я удалил все остальные части проекта и постарался сделать его максимально простым. Если вы перейдете на localhost: 8080, появится форма с двумя текстовыми полями для ввода двух имен и кнопки «Отправить». Первое имя будет сохранено в объекте Nominee, второе - в объекте Submitter. Когда вы нажмете «Отправить», он выполнит проверку в полях, чтобы убедиться, что ни один из них не пуст. Я отправлю код ниже и объясню свою проблему в конце.Проверка весны формы с помощью двух объектов
Application.java
package nomination;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.annotation.EnableJms;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.config.SimpleJmsListenerContainerFactory;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@SpringBootApplication
@EnableJms
@EnableWebMvc
public class Application {
public static void main(String[] args) throws Exception {
// Launch the application
SpringApplication.run(Application.class, args);
}
}
WebController.java
package nomination;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@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
package nomination;
import lombok.Data;
@Data
public class Nominee {
private String name;
}
NomineeValidatior.java
package nomination;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
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
package nomination;
import lombok.Data;
@Data
public class Submitter {
private String sname;
}
SubmitterValidator.java
package nomination;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
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>
успех.
: HTML<html><body>Form successfully submitted.</body></html>
Если я оставлю первое текстовое поле пустым (и заполнить или не заполнять во втором текстовом поле), на экране, который читает появляется сообщение об ошибке
Ошибка Whitelabel Page
Это приложение не имеет явного отображения для/ошибки, так что вы видите это как резерв. Вт 12 мая 13:10:17 AEST 2015 Была непредвиденная ошибка (type = Bad Request, status = 400). Не удалось выполнить проверку для object = 'nominee'. Количество ошибок: 1
Я не знаю, как исправить это, так что оставление первого текстового поля пустым не вызовет страницу с ошибкой whitelabel. Если я оставляю второе текстовое поле пустым, но заполняю первое, оно действует совершенно нормально, поэтому я не уверен, почему он вызывает ошибку, если я попробую по-другому. Любая помощь, связанная с этим, будет очень признательна.
Кроме того, возможно, вы заметили, что мне приходилось использовать «имя» и «змей» в качестве моих переменных в Номинанте и Отправитель, если я установил их как «имя», то он не работает должным образом. Если есть способ отредактировать его, чтобы они оба могли использовать «имя», мне было бы интересно узнать, как это сделать.
Редактировать: Решение проблемы. В 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.)
Попробуйте запустить logging для 'org.springframework.web' в DEBUG, чтобы узнать, что консоль говорит что-то интересное. – chrylis
Просто интересно узнать. Почему вы собираетесь на проверку на стороне сервера вместо проверки на стороне клиента (на основе javascript) здесь – Thomas
Нет настоящей причины. Используя Spring Boot в первый раз, просто играя с ним, чтобы научить себя, как это работает, увидел, что у него была своя реализация проверки формы и он хотел попытаться заставить его работать. – Jordan