@ModelAttribute和抽象类
问题内容:
我知道也有类似的问题。它们中给出的示例过于零散且不清楚。
我需要通过发送POST的页面上的表单来编辑实体。标准方法是在控制器中使用带有@ModelAttribute和validator的参数的方法。如果一种形式服务于抽象类的某个子类,则必填字段的生成不会有问题,但是控制器中会存在问题。
据我了解,@
ModelAttribute以这种方式工作:它初始化所需的对象类,然后收集其请求参数的字段。当然,如果对象是抽象类,则无法初始化。因此,该窗体具有一个字段,该字段将指示要初始化的子类。接下来,我们需要编写代码的安逸性,它将读取此属性并初始化正确的子类。应该是什么
我看到了有关Converter,PrepertyEditor,WebDataBinder的零碎示例,但很难将所有内容放在一起。
所以。有以下层次结构:
public abstract class Person {role, name, email, password ...}
public class Student extends Person {}
public class Lecturer extends Person {}
其中包含一个控制器和方法:
@RequestMapping (Path = "/ persons / uid {personId} / edit",
method = RequestMethod.GET)
public String editPerson (@PathVariable Integer personId, Model model) {
Person find = personDAO.read (personId);
model.addAttribute ( "person", find);
return "editPerson";
}
@RequestMapping (Path = "/ persons / uid {personId} / edit",
method = RequestMethod.POST)
public String editPersonPost (@PathVariable Integer personId,
@Valid @ModelAttribute ( "Person") Person person,
BindingResult result) {
if (result.hasErrors ()) return "editPerson error = true?";
personDAO.update (person);
return "redirect: / persons / uid" + personId + "saved = true?";
}
还有一个具有以下形式的JSP:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<h1>${person.name}</h1>
<form:form action="edit" method="post" commandName="person">
<input type="hidden" value="${person.role}" name="person_type" />
<table>
<tr>
<td>Password</td>
<td><form:input path="httpAuth.password" type="password"/></td>
<td><form:errors path="httpAuth.password" cssClass="error"></form:errors></td>
</tr>
<tr>
<td>Email</td>
<td><form:input path="email" /></td>
<td><form:errors path="email" cssClass="error"></form:errors></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="Save"></td>
<td></td>
</tr>
</table>
</form:form>
另外,转换器已经被编写,但是我怀疑是否有必要,或者这样做(继承另一个类…)
public class PersonConverter implements Converter <String, Person> {
public Person convert (String personType) {
Person person = null;
switch (personType) {
case "Student":
person = new Student ();
break;
case "Lecturer":
person = new Lecturer ();
break;
default:
throw new IllegalArgumentException (
"Unknown person type:" + personType);
}
return person;
}}
已在ConversionService中注册
<bean class="org.springframework.context.support.ConversionServiceFactoryBean"
id="theConversionService">
<property name="converters">
<list>
<bean class="schedule.service.PersonConverter"></bean>
</list>
</property>
</bean>
<mvc:annotation-driven conversion-service="theConversionService" validator="validator"/>
尽管如此,仍然缺少一些东西,那就是一种person_type
将从请求参数中获取并提供给转换器的方法,它将通过自动绑定机制将方法的结果返回给控制器。
请帮帮我。
问题答案:
您只需要确保下面的元素
<input type="hidden" value="${person.role}" name="person_type" />
将其命名属性更改为person
<input type="hidden" value="${person.role}" name="person" />
使其与控制器中的model属性匹配
public String editPersonPost (@PathVariable Integer personId,
@Valid @ModelAttribute ( "person") Person person,
BindingResult result)
这就是它的工作方式。
当接收到请求并且Spring需要创建model属性时,它将检查该属性是否已经存在。如果它不存在并且没有匹配名称的请求参数,它将使用参数类的默认构造函数创建一个新对象
如果存在并且匹配参数类型,它将继续绑定请求参数。如果不兼容或具有相同名称的请求参数,它将尝试找到能够将当前值转换为所需类型的转换器。
如果转换成功,它将请求参数绑定到结果,否则将引发异常
在您的情况下,person属性作为字符串发送。Spring将尝试将其转换为Person。在绑定之前,它将选择PersonConverter进行转换为适当的子类