Spring интерфейс как параметр @ModelAttribute

У меня есть UsersController с методом:

@RequestMapping(value={"/new"}, method=RequestMethod.GET)
public String showCreationForm(@ModelAttribute User user){
    return "user_registration_form";
}

который отображает регистрационную форму. Я хочу сохранить модульность (было бы неплохо использовать этот контроллер в каком-то другом проекте) в моем проекте, поэтому User — это интерфейс, и есть его реализация — UserImpl. Проблема в том, что Spring не может создать пользовательский интерфейс. Есть ли способ настроить Spring для использования некоторой реализации пользователя по умолчанию?


person Bladositto    schedule 30.08.2012    source источник
comment
Почему вы хотите, чтобы Spring создавал экземпляр вашего класса? Spring предлагает AOP и DI, если вы хотите их использовать, вам следует создать bean-компонент с областью сеанса или областью запроса.   -  person Boris Treukhov    schedule 30.08.2012
comment
@Modelattribute делает за меня установку.   -  person Bladositto    schedule 31.08.2012
comment
Отвечает ли это на ваш вопрос? Атрибут Spring MVC ModelAttribute как интерфейс   -  person Jacob van Lingen    schedule 23.11.2020


Ответы (2)


Вы можете предоставить объект для заполнения данными запроса, используя @ModelAttribute-аннотированный метод:

@ModelAttribute
public User createUser() {
    return new UserImpl();
}
person axtavt    schedule 30.08.2012
comment
Не совсем то, что я искал. Я пытаюсь избежать прямых вызовов UserImpl. Одна из идей — использовать интерфейс EmptyUserFactory в контроллере. Его реализация будет внедрена и использована для извлечения объекта UserImpl. Но, может быть, есть идея получше? - person Bladositto; 30.08.2012
comment
Я только что понял, что решение из моего предыдущего комментария дерьмовое. Я бы потерял возможность проверять пользователя с помощью аннотации @Valid. - person Bladositto; 30.08.2012

Создайте простой класс, минимально реализующий интерфейс. Это та же идея, что и интерфейс, но это класс. Он не содержит ни вашей логики, ни проверки, ни чего-либо еще. Это просто простейшая реализация интерфейса, назовите ее UserSimple, и она реализует ваш интерфейс. Он называется объектом передачи данных.

public class UserSimple implements User {
    String name;
    String address;
    //getters and setters only
}

Добавьте преобразователь, который копирует реальные свойства UserImpl в UserSimple.

@Component
public class ImplToSimpleConverter 
        implements Converter<UserImpl, UserSimple> {

    @Override
    public UserSimple convert(UserImpl source) {
        UserSimple target = new UserSimple();
        BeanUtils.copyProperties(source, target);
        return target;
    }
    
}

Используйте UserSimple в обработчике.

@RequestMapping(value={"/new"}, method=RequestMethod.GET)
public String showCreationForm(@ModelAttribute UserSimple user){
    return "user_registration_form";
}

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

person downeyt    schedule 01.08.2020