Я использую Spring 2.5 и использую аннотации для настройки своих контроллеров. Мой контроллер работает нормально, если я не реализую никаких дополнительных интерфейсов, но контейнер Spring не распознает сопоставление контроллера / запроса, когда я добавляю реализации интерфейса.
Я не могу понять, почему добавление реализации интерфейса портит конфигурацию контроллера и сопоставления запросов. Есть идеи?
Итак, это работает:
package com.shaneleopard.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.shaneleopard.model.User;
import com.shaneleopard.service.UserService;
import com.shaneleopard.validator.RegistrationValidator;
import com.shaneleopard.web.command.RegisterCommand;
@Controller
public class RegistrationController {
@Autowired
private UserService userService;
@Autowired
private Md5PasswordEncoder passwordEncoder;
@Autowired
private RegistrationValidator registrationValidator;
@RequestMapping( method = RequestMethod.GET, value = "/register.html" )
public void registerForm(@ModelAttribute RegisterCommand registerCommand) {
// no op
}
@RequestMapping( method = RequestMethod.POST, value = "/register.html" )
public String registerNewUser( @ModelAttribute RegisterCommand command,
Errors errors ) {
String returnView = "redirect:index.html";
if ( errors.hasErrors() ) {
returnView = "register";
} else {
User newUser = new User();
newUser.setUsername( command.getUsername() );
newUser.setPassword( passwordEncoder.encodePassword( command
.getPassword(), null ) );
newUser.setEmailAddress( command.getEmailAddress() );
newUser.setFirstName( command.getFirstName() );
newUser.setLastName( command.getLastName() );
userService.registerNewUser( newUser );
}
return returnView;
}
public Validator getValidator() {
return registrationValidator;
}
}
но это не так:
package com.shaneleopard.web.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.providers.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.shaneleopard.model.User;
import com.shaneleopard.service.UserService;
import com.shaneleopard.validator.RegistrationValidator;
import com.shaneleopard.web.command.RegisterCommand;
@Controller
public class RegistrationController extends ValidatingController {
@Autowired
private UserService userService;
@Autowired
private Md5PasswordEncoder passwordEncoder;
@Autowired
private RegistrationValidator registrationValidator;
@RequestMapping( method = RequestMethod.GET, value = "/register.html" )
public void registerForm(@ModelAttribute RegisterCommand registerCommand) {
// no op
}
@RequestMapping( method = RequestMethod.POST, value = "/register.html" )
public String registerNewUser( @ModelAttribute RegisterCommand command,
Errors errors ) {
String returnView = "redirect:index.html";
if ( errors.hasErrors() ) {
returnView = "register";
} else {
User newUser = new User();
newUser.setUsername( command.getUsername() );
newUser.setPassword( passwordEncoder.encodePassword( command
.getPassword(), null ) );
newUser.setEmailAddress( command.getEmailAddress() );
newUser.setFirstName( command.getFirstName() );
newUser.setLastName( command.getLastName() );
userService.registerNewUser( newUser );
}
return returnView;
}
public Validator getValidator() {
return registrationValidator;
}
}
Не похоже, что вы импортируете ValidatingController - какое полное имя класса?
Я импортирую это. Он находится в том же пакете, что и приведенный выше пример контроллера. Я должен добавить, что приведенный выше код работает, когда я расширяю базовый класс ValidatingController, но когда я кодирую ValidatingController в качестве интерфейса и реализую его RegistrationController, он ломается.





Я думаю, вы обнаружите, что проблема связана с наследованием и использованием аннотаций, они плохо сочетаются.
Вы пытались реализовать описанное выше, используя наследование и SimpleFormController, со всеми остальными деталями, настроенными в контексте вашего приложения? Это, по крайней мере, сузит проблему до аннотаций и наследования.
Layne, вы описали проблему как возникающую, когда ваш класс контроллера реализует интерфейс, но в предоставленном вами примере кода проблема возникает, когда ваш класс контроллера расширяет другой ваш класс, ValidatingController.
Возможно, родительский класс также определяет некоторые аннотации Spring, и контейнер Spring первым заметил их и классифицировал класс контроллера как управляемый объект этого типа и не потрудился проверить аннотацию @Controller, которую вы также определили в подклассе. Просто предположение, но если это удастся, я предлагаю сообщить об этом команде Spring, поскольку это звучит как ошибка.
По умолчанию прокси JDK создаются с использованием интерфейса, и если контроллер реализует интерфейс, аннотация RequestMapping игнорируется, поскольку targetClass не используется
Добавьте это в конфигурацию контекста сервлета:
<aop:aspectj-autoproxy proxy-target-class = "true"/>
Я должен добавить, что контроллеры зарегистрированы со следующим в моей конфигурации контекста Spring: <context: component-scan base-package = "com.shaneleopard.web" /> и с использованием DefaultAnnotationHandlerMapping и AnnotationMethodHandlerAdapter