Как реализовать Spring MvcAnnotationDriven 3.1? - PullRequest
1 голос
/ 20 марта 2011

Это пример кода из Spring 3.1 Spring Source Blog: от XML до @ Configuration Я пытаюсь реализовать в своем приложении (что было сделано в Spring 2.0 не мной, так что это много обучения ).

@FeatureConfiguration
class MvcFeatures {

    @Feature
    public MvcAnnotationDriven annotationDriven(ConversionService conversionService) {
        return new MvcAnnotationDriven().conversionService(conversionService)
            .argumentResolvers(new CustomArgumentResolver());
    }

    // ...

}

Однако я не могу понять смысл .argumentResolvers (новый CustomArgumentResolver ()) и их CustomArgumentResolver выглядит ниже. Какой в ​​этом смысл?

public class CustomArgumentResolver implements WebArgumentResolver {

    @Override
    public Object resolveArgument(MethodParameter param, NativeWebRequest request) throws Exception {
        RequestAttribute attr = param.getParameterAnnotation(RequestAttribute.class);
        if (attr != null) {
            return request.getAttribute(attr.value(), WebRequest.SCOPE_REQUEST);
        } else {
            return WebArgumentResolver.UNRESOLVED;
        }
    }
}

Ответы [ 2 ]

3 голосов
/ 21 марта 2011

Чтобы добавить ответ @ GaryF и прояснить некоторые моменты, Spring 2.5 представил аннотированные контроллеры, которые заменили старые контроллеры в стиле интерфейса Spring 2.0. Эти новые контроллеры имеют методы без фиксированных параметров - метод объявляет параметры, необходимые для его работы, и ничего более.

Например, скажем, для метода контроллера требуется одна вещь, чтобы выполнить свою работу - параметр запроса, который содержит идентификатор объекта из базы данных. В Spring 2.0 вам нужно реализовать что-то вроде AbstractController.handleRequestInternal(), например,

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
   String id = request.getParameter("id");
   MyThing obj = getObjById(id);
   //... do stuff and return ModelAndView
}

Пружина 2.5 сделала это проще:

@RequestMapping
public ModelAndView handle(String id) {
   MyThing obj = getObjById(id);
   //... do stuff and return ModelAndView
}

Здесь мы объявляем параметры только для того, что нам нужно.

Пока все хорошо, но тут появляется пользовательский WebArgumentResolver. Скажем, я хочу полностью удалить getObjById из моего контроллера, потому что, возможно, я думаю, что он загромождает код, и, возможно, он используется во многих другие методы контроллера. Вместо этого я хочу сделать это:

@RequestMapping
public ModelAndView handle(MyThing id) {
   //... do stuff and return ModelAndView
}

Это еще проще и имеет минимальный шаблонный код. Пользовательский WebArgumentResolver может быть зарегистрирован в контексте приложения, который распознает параметры типа MyThing и знает, как извлечь информацию из запроса. Spring вызывает этот распознаватель и передает результат в метод контроллера.

Пользовательские распознаватели обычно не используются, но могут быть очень полезны в правильной ситуации.

В примере в вашем вопросе используется CustomArgumentResolver для разрешения пользовательского класса RequestAttribute. Средство распознавания извлекает атрибуты запроса и связывает их с RequestAttribute объектами, так что они могут быть объявлены как параметры метода контроллера.

1 голос
/ 21 марта 2011

WebArgumentResolver s - это способ указать, как следует разрешать параметры методов, сопоставленных с MVC. Если вы хотите использовать пользовательский объект в качестве параметра для метода, сопоставленного с MVC, Spring попытается выяснить, как по-своему это осмыслить. Обычно это происходит через связывание, когда некоторые http-параметры, которые вы отправляете, совпадают с полями объекта, а Spring сопоставляет их и создает для вас новый объект.

Если вы когда-либо сталкивались с ситуацией, когда представленные параметры не очень точно совпадают с параметрами вашего метода, WebArgumentResolvers поможет заполнить этот пробел: вы предоставляете пользовательскую логику, чтобы Spring не должен был ее выяснять.

В вашем примере, param - один из таких параметров, который нужно сопоставить. Этот фрагмент пользовательского кода сначала проверяет, имеет ли параметр аннотацию @RequestAttribute. Если это так, то пользовательский код извлекает значение из этого объекта и ищет его как атрибут в запросе http, возвращая его. Если у него нет этой аннотации, метод возвращает значение UNRESOLVED, которое просто указывает, что этот WebArgumentResolver ничего не знает об этом конкретном параметре, и Spring должен попробовать другой метод (например, привязку).

...