Spring MVC: привязать атрибут запроса к параметру метода контроллера
В Spring MVC легко привязать параметр запроса к параметрам метода, обрабатывающим запрос. Я просто использую @RequestParameter("name")
. Но могу ли я сделать то же самое с атрибутом запроса? В настоящее время, когда я хочу получить доступ к атрибуту запроса, я должен сделать следующее:
MyClass obj = (MyClass) request.getAttribute("attr_name");
Но я действительно хотел бы использовать что-то вроде этого:
@RequestAttribute("attr_name") MyClass obj
К сожалению, это не работает. Могу ли я каким-то образом расширить функциональность Spring и добавить свои собственные "связующие"?
ИЗМЕНИТЬ (чего я пытаюсь достичь): я сохраняю в настоящее время зарегистрированный пользовательский атрибут внутреннего запроса. Поэтому всякий раз, когда я хочу получить доступ к уже зарегистрированному пользователю (что почти во всех методах), я должен написать эту дополнительную строку user = (User) request.getAttribute("user");
. Я хотел бы сделать это как можно короче, желательно ввести его как параметр метода. Или, если вы знаете другой способ, как передать что-то через перехватчики и контроллеры, я был бы рад услышать это.
Ответы
Ответ 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