2016-05-18 2 views
1

Я знаю, что были похожие вопросы. Приведенные в них примеры слишком фрагментарны и неясны.@ModelAttribute и abstract class

Мне нужно отредактировать объекты через форму на странице, которая отправляет POST. Стандартный метод - это метод в контроллере, который использует параметр с @ModelAttribute и валидатор. Если одна форма обслуживает некоторый подкласс абстрактного класса, нет проблем с генерацией необходимых полей, но в контроллере есть проблема.

Как я понимаю, @ModelAttribute работает таким образом: он инициализирует желаемый класс объекта и затем собирает его поля параметров запроса. Конечно, если объект является абстрактным классом, его нельзя инициализировать. Поэтому в форме есть поле, которое укажет, какой подкласс инициализируется. Затем нам нужен мир кода, который будет читать этот атрибут и инициализировать правильный подкласс. Что это должно быть? Я видел фрагментарные примеры о конвертере, PrepertyEditor, WebDataBinder, но сложно собрать все вместе.

So. Есть следующая иерархия:

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 из параметров запроса и передать его в преобразователь, и он будет возвращать результат метода контроллера с помощью механизмы автоматического связывания.

Помогите мне пожалуйста.

ответ

1

Вам просто нужно убедиться, что элемент ниже

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

имеет свой названный атрибут изменен на человека

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

так, что он соответствует атрибуту модели в контроллере

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

Вот как это работает.

Когда запрос получен, а Spring необходимо создать атрибут модели, он проверяет, существует ли атрибут. Если он не существует и нет параметра запроса совпадающего имени, он создает новый объект, используя конструктор по умолчанию класса параметров

Если он существует и соответствует типу аргумента, он продолжает связывать параметры запроса.Если он несовместим или доступен параметр запроса с тем же именем, он пытается найти преобразователь, способный преобразовать текущее значение в требуемый тип.

Если преобразование выполнено успешно, он связывает параметры запроса с результатом, иначе он выдает Исключение

В вашем случае атрибут person отправляется как строка. Весна попытается преобразовать его в Личность. Он выбирает ваш PersonConverter для преобразования в соответствующий подкласс до привязки