【问题标题】:Why does using @Valid with @ModelAttribute result in exception?为什么将@Valid 与@ModelAttribute 一起使用会导致异常?
【发布时间】:2019-05-21 18:50:53
【问题描述】:

我得到 "bean name 'person1' 的 BindingResult 和普通目标对象都不能用作请求属性"。这个问题的大多数答案都说我错过了 @ModelAttribute 注释,但我使用它并且仍然得到那个异常。

我使用多个控制器方法,并希望相同的模型在不同的方法中有不同的名称。当我使用 @ModelAttribute(name = "person1") 时会出现问题。如果我不命名它,它可以工作,但我在所有表单中都有相同的模型,并且在所有表单中显示相同的验证错误,即使我只填写一个。

这些是我的示例控制器方法:

@RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView index(HttpSession session) {
logger.info("opening index page");
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("person1", new Person("Maria Smith", null));
modelAndView.addObject("person", new Person("John Doe", null));
return modelAndView;
}

@RequestMapping(value = "/getPersonTree", method = RequestMethod.POST)
public ModelAndView getPersonTree(@Valid @ModelAttribute("person1") Person person, BindingResult bindingResult) {
    if (bindingResult.hasErrors()) {
        return new ModelAndView("index", "person1", person);
    } else {
        int id = databaseModel.getPersonID(person);
        person = databaseModel.setPersonTreeParents(databaseModel.getPersonTree(id));
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("getPersonTreeSuccess");
        modelAndView.addObject("person1", person);
        return modelAndView;
    }
}    }

@RequestMapping(value = "/insertPerson", method = RequestMethod.POST)
public ModelAndView insertPerson(@Valid @ModelAttribute Person person, 
BindingResult bindingResult) {
logger.info("insert person controller");
if (bindingResult.hasErrors()) {
    return new ModelAndView("index", "person", person);
} else {
    databaseModel.insert(person);
    ModelAndView modelAndView = new ModelAndView();
    modelAndView.setViewName("insertSuccess");
    modelAndView.addObject("person", person);
    return modelAndView;
}
}

这些是我的示例 jsps:

<f:form class="form-inline" action="getPersonTree"
modelAttribute="person1">

<f:label path="name">Person Name:</f:label>
<f:input path="name" type="text" />
<f:errors path="name" class="alert alert-danger"></f:errors>
<button class="btn btn-primary" type="submit">Get Person
    Tree</button>

</f:form>

<f:form class="form-inline" action="insertPerson"
modelAttribute="person">

<f:label path="name">Person Name:</f:label>
<f:input path="name" type="text" />
<f:errors path="name" class="alert alert-danger"></f:errors>


<f:label path="birthDate">Date of birth:</f:label>
<f:input type="date" path="birthDate" />
<f:errors path="birthDate" class="alert alert-danger"></f:errors>


<f:label path="gender">Gender:</f:label>
<%--                        <f:input path="gender" type="text" /> --%>
<f:radiobutton path="gender" value="male" />M
<f:radiobutton path="gender" value="female" />F
<f:errors path="gender" class="alert alert-danger"></f:errors>

<button class="btn btn-primary" type="submit">Add Person</button>

</f:form>

我希望自定义名称能够正常工作,因为有教程显示了具有自定义名称的此类示例,但我得到了例外。所以,我的问题是:任何人都可以展示在同一页面上使用多个表单处理多个 ModelAttributes 的正确方法,每个表单一个 ModelAttribute,但名称不同?

【问题讨论】:

  • 在上面的代码中删除@Valid也会删除异常,可能是什么问题?

标签: java validation spring-mvc jsp


【解决方案1】:

GET 处理程序中:

modelAndView.addObject("thisIsYourCommandName", person);

在 JSP 中:

<form modelAttribute="thisIsYourCommandName" ..../>

POST 处理程序中:

@RequestMapping(value = "/getPersonTree")
public ModelAndView getPersonTree(@ModelAttribute("thisIsYourCommandName") Person person, BindingResult result) {
    // ...
}

如果你的命令名是“person”而不是“thisIsYourCommandName”,你可以这样做

@ModelAttribute Person person

相同
@ModelAttribute("person") Person person

所以只需这样做:

GET处理程序:

modelAndView.addObject("person", new Person());
modelAndView.addObject("x", new Person());

Person 的表单:

<form:form modelAttribute="person" ...>

X 的表单:

<form:form modelAttribute="x" ...>

POST处理程序:

@ModelAttribute("person") Person person@ModelAttribute Person person

还有:

@ModelAttribute("x") Person person@ModelAttribute Person x

【讨论】:

  • 从您的回答中:正如我在问题中提到的那样,“Person 表单”部分对我有用,但我想多次使用它,它在所有表单中都给了我相同的验证错误。 “X 表格”部分给了我我也提到的例外情况。
  • @FalseScience 那是因为我认为你还没有这样做modelAndView.addObject("x", new Person());。您不能使用 1 个命令对象让多个表单以不同方式工作。您需要不同的命令对象。 (提醒一下,我在我的代码 sn-ps 中用小写的 x 写了)
  • 哦,好的,现在我像你说的那样尝试了:@RequestMapping(value = "/index", method = RequestMethod.GET) public ModelAndView index(@ModelAttribute Person person, @ModelAttribute Person person1, HttpSession session) { logger.info("opening index page"); person.setName("John Doe"); person1.setName("Maria Smith"); ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("person1", person1); modelAndView.addObject("person", person); return modelAndView; } 仍然得到同样的异常
  • POST处理程序中使用@ModelAttribute从模型中获取,而不是像这样在GET处理程序中。从GET 处理程序只需将命令对象添加到模型就足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 2014-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多