Подтвердить что ты не робот

Spring MVC: привязать атрибут запроса к параметру метода контроллера

В Spring MVC легко привязать параметр запроса к параметрам метода, обрабатывающим запрос. Я просто использую @RequestParameter("name"). Но могу ли я сделать то же самое с атрибутом запроса? В настоящее время, когда я хочу получить доступ к атрибуту запроса, я должен сделать следующее:

MyClass obj = (MyClass) request.getAttribute("attr_name");

Но я действительно хотел бы использовать что-то вроде этого:

@RequestAttribute("attr_name") MyClass obj

К сожалению, это не работает. Могу ли я каким-то образом расширить функциональность Spring и добавить свои собственные "связующие"?

ИЗМЕНИТЬ (чего я пытаюсь достичь): я сохраняю в настоящее время зарегистрированный пользовательский атрибут внутреннего запроса. Поэтому всякий раз, когда я хочу получить доступ к уже зарегистрированному пользователю (что почти во всех методах), я должен написать эту дополнительную строку user = (User) request.getAttribute("user");. Я хотел бы сделать это как можно короче, желательно ввести его как параметр метода. Или, если вы знаете другой способ, как передать что-то через перехватчики и контроллеры, я был бы рад услышать это.

4b9b3361

Ответ 1

Ну, я, наконец, немного понял, как работают модели, и что такое @ModelAttribute for. Вот мое решение.

@Controller 
class MyController
{
    @ModelAttribute("user")
    public User getUser(HttpServletRequest request) 
    {
        return (User) request.getAttribute("user");
    }

    @RequestMapping(value = "someurl", method = RequestMethod.GET)
    public String HandleSomeUrl(@ModelAttribute("user") User user)  
    {
        // ... do some stuff
    }
}

Метод getUser(), помеченный аннотацией @ModelAttribute, автоматически заполнит все параметры User user, отмеченные @ModelAttribute. Поэтому, когда вызывается метод HandleSomeUrl, вызов выглядит примерно как MyController.HandleSomeUrl(MyController.getUser(request)). По крайней мере, так я себе это представляю. Прохладно, что пользователь также доступен из представления JSP без каких-либо дополнительных усилий.

Это точно решает мою проблему, но у меня есть дополнительные вопросы. Есть ли общее место, где я могу поместить эти методы @ModelAttribute, чтобы они были распространены для всех моих контроллеров? Могу ли я каким-либо образом добавить атрибут модели изнутри метода preHandle() перехватчика?

Ответ 2

Использовать (с Spring 4.3) @RequestAttribute:

@RequestMapping(value = "someurl", method = RequestMethod.GET)
public String handleSomeUrl(@RequestAttribute User user) {
    // ... do some stuff
}

или если имя атрибута запроса не соответствует имени параметра метода:

@RequestMapping(value = "someurl", method = RequestMethod.GET)
public String handleSomeUrl(@RequestAttribute(name="userAttributeName") User user) {
    // ... do some stuff
}

Ответ 3

Я думаю, что вы ищете:

@ModelAttribute("attr_name") MyClass obj

Вы можете использовать это в параметрах для метода в вашем контроллере.

Вот ссылка a на вопрос с подробностями о нем Что такое @ModelAttribute в Spring MVC?

Этот вопрос ссылается на документацию Spring с некоторыми примерами ее использования. Вы можете видеть, что здесь

Обновление

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

@RequestMapping(value = "/account", method = RequestMethod.GET)
public ModelAndView displayAccountPage() {
    User user = new User(); //most likely you've done some kind of login step this is just for simplicity
    return new ModelAndView("account", "user", user); //return view, model attribute name, model attribute
}

Затем, когда пользователь отправляет запрос, Spring свяжет атрибут пользователя с объектом User в параметрах метода.

@RequestMapping(value = "/account/delivery", method = RequestMethod.POST)
public ModelAndView updateDeliverySchedule(@ModelAttribute("user") User user) {

    user = accountService.updateDeliverySchedule(user); //do something with the user

    return new ModelAndView("account", "user", user);
}

Ответ 4

Не самый элегантный, но работает как минимум...

@Controller
public class YourController {

    @RequestMapping("/xyz")
    public ModelAndView handle(
        @Value("#{request.getAttribute('key')}") SomeClass obj) {

        ...
        return new ModelAndView(...);
    }

}

Источник: http://blog.crisp.se/tag/requestattribute

Ответ 5

Из spring 3.2 это можно сделать еще лучше, используя аннотацию Springs ControllerAdvice. Это позволит вам получить совет, который добавляет @ModelAttributes в отдельный класс, который затем применяется ко всем вашим контроллерам.

Для полноты также можно сделать @RequestAttribute ( "attr-name" ) как есть. (ниже изменено эта статья в соответствии с нашими требованиями)

Сначала мы должны определить аннотацию:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface RequestAttribute {
    String value();
}

Затем нам понадобится [WebArgumentResolver] для обработки того, что необходимо сделать, когда атрибут привязан

public class RequestAttributeWebArgumentResolver implements WebArgumentResolver {

    public Object resolveArgument(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) throws Exception {
        // Get the annotation       
        RequestAttribute requestAttributeAnnotation = methodParameter.getParameterAnnotation(RequestAttribute.class);

        if(requestAttributeAnnotation != null) {
            HttpServletRequest request = (HttpServletRequest) nativeWebRequest.getNativeRequest();

            return request.getAttribute(requestAttributeAnnotation.value);
        }

        return UNRESOLVED;
    }
}

Теперь нам нужно добавить этот customresolver в конфигурацию, чтобы разрешить его:

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
    <property name="customArgumentResolver">
        <bean class="com.sergialmar.customresolver.web.support.CustomWebArgumentResolver"/>
    </property>
</bean>

И все готово!

Ответ 6

Да, вы можете добавить свои собственные "связующие" в атрибут запроса - см. spring-mvc-3-showcase или использовать решение @Peter Szanto.

В качестве альтернативы свяжите его как атрибут ModelAttribute, как рекомендовано в других ответах.

Как пользователь, который вы ввели в систему, вы хотите перейти в свой контроллер, вы можете рассмотреть Spring Безопасность. Тогда вы можете просто использовать Принцип, введенный в ваш метод:

@RequestMapping("/xyz")
public String index(Principal principle) {
    return "Hello, " + principle.getName() + "!";
}

Ответ 7

В Spring WebMVC 4.x он предпочитает использовать HandlerMethodArgumentResolver

@Override
public boolean supportsParameter(MethodParameter parameter) {
    return parameter.getParameterAnnotation(RequestAttribute.class) != null;
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
        NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
    return webRequest.getAttribute(parameter.getParameterAnnotation(RequestAttribute.class).value(), NativeWebRequest.SCOPE_REQUEST);
}

}

Затем зарегистрируйте его в RequestMappingHandlerAdapter