@ModelAttribute 和抽象类 [英] @ModelAttribute and abstract class

查看:34
本文介绍了@ModelAttribute 和抽象类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有类似的问题.其中给出的例子过于零碎和不清楚.

I know that there have been similar questions. The examples given in them are too fragmentary and unclear.

我需要通过发送 POST 的页面上的表单来编辑实体.标准方法是控制器中使用带有@ModelAttribute 和验证器的参数的方法.如果一个表单服务于某个抽象类的某个子类,那么必要字段的生成没有问题,但控制器有问题.

I need to edit the entities through a form on the page that sends the POST. The standard method is a method in the controller uses the parameter with @ModelAttribute and validator. If one form serves some subclass of an abstract class, there are no problems with the generation of the necessary fields, but there is a problem in the controller.

据我所知,@ModelAttribute 是这样工作的:它初始化所需的对象类,然后收集他的请求参数字段.当然,如果对象是抽象类,就不能初始化.因此,表单有一个字段,用于指示要初始化的子类.接下来,我们需要代码安宁,它将读取此属性并初始化正确的子类.应该是什么?我看到了有关 Converter、PrepertyEditor、WebDataBinder 的零散示例,但很难将所有内容放在一起.

As I understand it, @ModelAttribute works this way: it initializes the desired object class, and then collects his fields of the parameters of the request. Of course, if the object is an abstract class, it can not be initialized. Therefore, the form has a field that will indicate what subclass to initialize. Next, we need peace of code, that will read this attribute and initialize the correct subclass. What should it be? I saw fragmentary examples about the Converter, PrepertyEditor, WebDataBinder, but difficult to put everything together.

所以.有以下层次结构:

So. There are the following hierarchy:

public abstract class Person {role, name, email, password ...}
public class Student extends Person {}
public class Lecturer extends Person {}

里面有一个控制器和方法:

There is a controller and methods in it:

@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:

And there is a JSP with a form:

<%@ 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>

另外,转换器已经写好了,但我怀疑是否有必要,要不然就去做(继承另一个类...)

Also, the converter has been written, but I doubt whether it is necessary, or else do it (inheriting another class ...)

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

Which is registered with 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 并将其提供给转换器,并且它将通过自动绑定机制返回控制器方法的结果.

Nevertheless, something is missing, that is a method that will take person_type from request parameters and give it to converter, and it will return a result of the method the controller via the automatic binding mechanisms.

请帮帮我.

推荐答案

你只需要保证下面的元素

You just need to ensure that the element below

<input type="hidden" value="${person.role}" name="person_type" />

已将其命名属性更改为 person

has its named attribute changed to person

<input type="hidden" value="${person.role}" name="person" />

使其与控制器中的模型属性相匹配

so that it matches the model attribute in your controller

public String editPersonPost (@PathVariable Integer personId,
        @Valid @ModelAttribute ( "person") Person person,
        BindingResult result)

这就是它的工作原理.

当收到请求并且 Spring 需要创建模型属性时,它会检查该属性是否已存在.如果它不存在并且没有匹配名称的请求参数,则使用参数类的默认构造函数创建一个新对象

When a request is received and Spring needs to create the model attribute it checks if the attribute already exists. If it doesn`t exist and there is no request parameter of matching name it creates a new object using the default constructor of the parameter class

如果它存在并且匹配参数类型,它将继续绑定请求参数.如果它不兼容或同名请求参数可用,它会尝试找到能够将当前值转换为所需类型的转换器

If it exists and matches the argument type it proceeds to bind the request parameters. If it is not compatible or a request parameter of same name is available it tries to find a converter capable of converting the current value to the required type

如果转换成功则将请求参数绑定到结果,否则抛出异常

If conversion is successful it binds the request parameters to the result otherwise it throws an Exception

在您的情况下,person 属性作为字符串发送.Spring 将尝试将其转换为 Person.它选择您的 PersonConverter 在绑定之前转换为适当的子类

In your case the person attribute is sent as a String. Spring will attempt to convert it to a Person. It picks your PersonConverter to do the conversion to an appropriate subclass before binding

这篇关于@ModelAttribute 和抽象类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆