Проблема Spring MVC и аннотированных контроллеров:

У меня странная проблема с аннотированными контроллерами и Spring MVC. Я пытался использовать аннотированные контроллеры для примера приложения MVC, которое Spring поставляет со своей документацией. Я использовал версию 2.5.

Когда я указываю @RequestMapping на уровне типа, я получаю «ОШИБКА HTTP: 500 Нет адаптера для обработчика [имя класса контроллера]: реализует ли ваш обработчик поддерживаемый интерфейс, такой как контроллер?

Если я включу его на уровень метода, он отлично работает без проблем. Добавление или удаление адаптеров дескрипторов по умолчанию для файлов контекста не имело значения:

Наконец, я прибегнул к @RequestMapping на уровне контроллера, а также на уровне метода, и это сработало. Кто-нибудь знает, в чем может быть дело?

Вот пример кода:

Это не сработало:

@Controller
@RequestMapping("/*")
public class InventoryController {
    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ProductManager productManager;


    public ModelAndView inventoryHandler() {
        String now = (new java.util.Date()).toString();
        logger.info("returning hello view with " + now);
        Map<String, Object> myModel = new HashMap<String, Object>();
        myModel.put("now", now);
        myModel.put("products", this.productManager.getProducts());
        return new ModelAndView("hello", "model", myModel);
    }
}

Это сработало:

@Controller

public class InventoryController {
    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ProductManager productManager;

    @RequestMapping("/hello.htm")
    public ModelAndView inventoryHandler() {
        String now = (new java.util.Date()).toString();
        logger.info("returning hello view with " + now);
        Map<String, Object> myModel = new HashMap<String, Object>();
        myModel.put("now", now);
        myModel.put("products", this.productManager.getProducts());
        return new ModelAndView("hello", "model", myModel);
    }
}

Это также сработало:

@Controller
@RequestMapping("/*")
public class InventoryController {
    protected final Log logger = LogFactory.getLog(getClass());

    @Autowired
    private ProductManager productManager;

    @RequestMapping( method = RequestMethod.GET, value = "/hello.htm" )
    public ModelAndView inventoryHandler() {
        String now = (new java.util.Date()).toString();
        logger.info("returning hello view with " + now);
        Map<String, Object> myModel = new HashMap<String, Object>();
        myModel.put("now", now);
        myModel.put("products", this.productManager.getProducts());
        return new ModelAndView("hello", "model", myModel);
    }
}

Есть идеи, что здесь происходит? Я много искал и не нашел решения. Я также пробовал с 2.5.6, и проблема была похожей.


person Shaw    schedule 29.12.2009    source источник


Ответы (3)


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

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

Учтите, что одним из преимуществ аннотированных контроллеров является то, что вы можете иметь столько @RequestMapping-аннотированных методов в своем классе, сколько захотите.

person skaffman    schedule 29.12.2009
comment
Спасибо. Я действительно сходил с ума по этому поводу. Я последовал идее из этого блога, интересно, как это сработало для автора блога: cchweblog.wordpress.com/2009/06/20/ РЕДАКТИРОВАТЬ: я понимаю преимущества наличия его в каждом методе. На самом деле было бы неплохо поместить его даже для одного метода в классе, кто знает, может быть, позже я добавлю больше методов! - person Shaw; 29.12.2009
comment
У него тоже есть @RequestMapping методы. - person skaffman; 29.12.2009
comment
Ах! Хороший улов .. Я действительно пропустил это .. не знаю, как я проглядел .. Еще раз спасибо! - person Shaw; 29.12.2009

Вам не нужно использовать @RequestMapping в классе. Это просто удобство. Вам нужны аннотации @RequestMapping уровня метода.

Учитывая это:

@Controller
public class InventoryController {
...
@RequestMapping("/inventory/create/{id}")
public void create(...){}

@RequestMapping("/inventory/delete/{id}")
public void delete(...){}
...

Вы можете исключить инвентарную часть URI.

@Controller
@RequestMapping("/inventory")
public class InventoryController {
...
@RequestMapping("create/{id}")
public void create(...){}

@RequestMapping("delete/{id}")
public void delete(...){}
...
person Gene De Lisa    schedule 11.05.2011

Это связано с тем, что первая конфигурация не указывает, какой метод класса вызывается.

person rodrigoap    schedule 29.12.2009