2013-02-22 3 views
18

Spring MVC에서는 요청을 처리하는 메소드 매개 변수에 매개 변수을 쉽게 바인딩 할 수있다. 방금 @RequestParameter("name")을 사용합니다. 하지만 속성 요청으로 동일한 작업을 수행 할 수 있습니까? 내가 요청 속성에 액세스 할 때 현재, 나는 다음을 수행해야합니다 :Spring MVC : 컨트롤러 메소드 매개 변수에 대한 요청 속성 바인드

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

을하지만 난 정말이 대신 같은 것을 사용하고 싶습니다 : 불행하게도

@RequestAttribute("attr_name") MyClass obj 

, 그렇지 않습니다 이런 식으로 일하십시오. 어떻게 든 스프링 기능을 확장하고 내 "바인더"를 추가 할 수 있습니까?

편집(달성하고자하는 것) : 현재 요청한 사용자의 내부 속성을 저장합니다. 그래서 내가 현재 로그인 한 사용자 (모든 메소드 내부에 있음)에 액세스하려고 할 때마다이 여분의 줄을 작성해야합니다. user = (User) request.getAttribute("user");. 가능한 한 짧게 만들고 싶습니다. 메소드 매개 변수로 삽입하는 것이 바람직합니다. 아니면 인터셉터와 컨트롤러를 통해 무언가를 전달하는 또 다른 방법을 알고 있다면 나는 그것을 듣게 될 것이다.

@ModelAttribute("attr_name") MyClass obj 

당신은 당신의 컨트롤러 방법에 대한 매개 변수에 그것을 사용할 수 있습니다

답변

29

글쎄, 나는 마침내 모델이 어떻게 작동하는지 조금 이해하고 무엇을위한 @ModelAttribute입니다. 여기 내 해결책이있다.

@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() 메소드 내부에서 모델 속성을 추가 할 수 있습니까?

+0

이것은 완벽합니다! 고맙습니다. – Raff

+0

매개 변수 이름이 모델 객체의 속성과 일치하면 추가 getUser 메소드가 필요 없으며 Spring은 자동으로 해당 속성을 설정합니다. – chrismarx

+1

이 방법으로 메소드의 User 객체는 뷰 모델뿐만 아니라 속성에서도 검색됩니다 들어오는 요청 또는 양식 매개 변수에 의해 Y 인드 (및 겹쳐 쓰기)됩니다. 예를 들어, User 객체에 많은 사용자 객체가있는 id 속성이 있고 요청 URL이나 양식에도 관련이없는 id 매개 변수가 있으면 User 객체의 id를 덮어 씁니다. 이것은 한때 내 코드에서 불쾌한 버그를 만들었습니다. 이 특별한 경우에는 @ModelAttribute의 양식 바인딩 속성을 원하지 않습니다. 대안은'User u = (User) model.get ("user");'를 사용하는 것입니다. – klausch

3

나는 당신을 위해 무엇을 찾고있는 것이라고 생각합니다. 여기

은 너무 그것을 사용하는 몇 가지 예제와 함께 봄 문서에 그 질문 링크 What is @ModelAttribute in Spring MVC?

에 대한 자세한 내용과 질문에 대한 링크이다. 당신은 내가 당신이 당신의 페이지를 설정하는 방법을 잘 모르겠어요 here

업데이트

것을 볼 수 있습니다,하지만 당신은 모델로, 사용자가 몇 가지 방법을 속성에 추가 할 수 있습니다. 아래에 간단한 예제를 설정했습니다.

@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은 메소드 매개 변수에서 사용자 속성을 사용자 객체에 바인딩합니다.

@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); 
} 
+0

감사합니다,하지만 난 다른 뭔가를 달성하기 위해 노력 하였다 .. 어쩌면 나는 그것을 설명해야합니다. 요청 된 속성을 사용하여 현재 로그인 한 사용자를 저장합니다. 그래서 당신이'User user = (User) session.getAttribute ("user");를 호출 할 때'user = (User) request.getAttribute ("user");'를 호출합니다. 그러나 모든 단일 방법에서이를 작성하는 것은 상당히 성가시다. 가능한 한 짧게 만들고 싶습니다. 메서드 매개 변수로 삽입하는 것이 좋습니다. – tobik

+0

이 방법을 사용하여 계속 작업 할 수 있습니다. 모델에 User 객체를 추가하기 만하면됩니다. 그런 다음 액세스 할 수 있습니다. 이를 수행 할 수있는 몇 가지 방법이 있습니다. 내 대답을 업데이트 할게. – ssn771

+0

나는'@ SessionAttributes'에 익숙하지 않지만 그것은 당신에게도 도움이 될 것입니다.다음은 [link] (http://static.springsource.org/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-sessionattrib) 문서입니다. – ssn771

0

스프링 3.2부터는 스프링 ControllerAdvice 주석을 사용하여 더 멋지게 수행 할 수 있습니다. 이렇게하면 별도의 클래스에 @ModelAttributes를 추가하는 조언을 가질 수 있으며 모든 관리자에게 적용됩니다.

완전성을 위해 실제로 @RequestAttribute ("attr-name")을 그대로 사용할 수도 있습니다.

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

그런 다음 우리는 속성이 될 때 수행에 필요한 사항을 처리하기 위해 [WebArgumentResolver]이 필요합니다

먼저 (우리의 요구에 맞게 this article에서 수정 이하) , 우리는 주석을 정의해야 바인딩

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> 

이제 끝났습니다!

2

가장 우아한 아니지만, 적어도 작동 ...

@Controller 
public class YourController { 

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

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

} 

출처 : http://blog.crisp.se/tag/requestattribute

0

예, 당신이 요청 속성에 자신의 '바인더'를 추가 할 수 있습니다 - spring-mvc-3-showcase를 참조하거나 사용 @Peter Szanto의 솔루션.

또는 다른 답변에서 권장하는 것처럼 ModelAttribute로 바인딩하십시오.

컨트롤러에 전달하려는 로그인 사용자이므로 Spring Security을 고려할 수 있습니다.

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

봄 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); 
} 

}

다음

4
RequestMappingHandlerAdapter에 등록 : 그럼 당신은 단지 Principle 당신의 방법에 주입 할 수 있습니다

사용 (스프링 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 
} 
관련 문제