2013-06-26 12 views
7

Używam MVC wiosny 3.2.2Wiosna HandlerMethodArgumentResolver nie wykonując

mam zdefiniowaną klasę zwyczaj HandlerMethodArgumentResolver jak ten

public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver { 

    public CurrentUserArgumentResolver() { 
    System.out.println("Ready"); 
    } 

    @Override 
    public boolean supportsParameter(MethodParameter parameter) { 
    return parameter.hasParameterAnnotation(CurrentUser.class); 
    } 

    @Override 
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, 
     NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception { 

     Principal principal = webRequest.getUserPrincipal(); 
     System.out.println("*** Principal ***: " + principal); 
     return principal; 
    } 
} 

i dodaje następujące do mojego app-servlet.xml

<mvc:annotation-driven> 
    <mvc:argument-resolvers> 
    <beans:bean class="my.package.CurrentUserArgumentResolver" lazy-init="false"/> 
    </mvc:argument-resolvers> 
</mvc:annotation-driven> 

i utworzyli adnotację dla CurrentUser

@Target(ElementType.PARAMETER) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface CurrentUser { 

} 

Po uruchomieniu aplikacji klasa jest konstruowana tak, jak widzę komunikat dziennika "Gotowy", ale resolver nie jest wykonywany, gdy przypisuję metodę kontrolera jako taką (w klasie, która ma adnotację @Controller)

@RequestMapping(method = RequestMethod.POST, value = "/update") 
public ModelAndView update(@RequestParam MultipartFile background, @CurrentUser Principal principal) { 
... 
} 

Jeśli umieściłem punkty przerwania na obu metodach w klasie CurrentUserArgumentResolver, żadna z nich nie działa. Więc nie jestem pewien, czego mi brakuje?

+0

wyglądać dokładnie jak moja odpowiedź na to pytanie: http://stackoverflow.com/questions/8764545/best-practice-for-getting-active-users-userdetails/8769670#8769670 - Nie widzę żadnego błędu w opublikowanym kodzie. Więc może problem jest gdzieś indziej: sprawdź, czy wszystko jest w porządku i jest poprawnie wdrożone. Sprawdź, czy istnieje tylko jeden MVC: anotationdriven. Sprawdź, czy wiązka kontrolera jest znaleziona tylko przez skanowanie komponentu z app-servlet.xml. – Ralph

+0

Tak, mój kod był oparty na kombinacji twoich odpowiedzi i wiosennych dokumentów. Cały kod kompiluje się, a metoda kontrolera jest wywoływana poprawnie, po prostu jest ona zerowa. Przynajmniej spodziewałbym się, że punkt przerwania na "SupportParameter" zostanie wywołany. –

+0

Jaka jest wartość parametru metody kontrolera (zleceniodawcy)? Czy jest pusty? – Ralph

Odpowiedz

3

OK Ustaliłem, że Spring już rozwiązał główny obiekt w powyższym przykładzie, więc mój argument rozstrzygający nie był kopiący. Byłem leniwy i dodałem adnotację @CurrentUser do istniejącego parametru.

Więc zmieniłem mój przykład

@RequestMapping(method = RequestMethod.POST, value = "/update") 
public ModelAndView update(@RequestParam MultipartFile background, @CurrentUser Principal principal) { 
    ... 
} 

używać moja klasa User Model

@RequestMapping(method = RequestMethod.POST, value = "/update") 
public ModelAndView update(@RequestParam MultipartFile background, @CurrentUser User user) { 
    ... 
} 

i teraz to działa!

+1

Dziękuję za tę odpowiedź - wskazał mi to w dobrym kierunku. Jedną z moich klas, którą chciałem rozwiązać, było przedłużenie AbstractAuthenticationToken i jako taka została ona rozwiązana przez Springa bez mojej wiedzy. Moim rozwiązaniem było stworzenie interfejsu, użycie go jako parametru metody i rozwiązanie interfejsu. –

+0

@ PetrDvořák Miałem dokładnie ten sam problem. Naprawiłem to również poprzez podłączenie do interfejsu. –

12

Jeśli ktokolwiek chce priorytet niestandardowych teleskopowe ponad koparki domyślnych dodanych przez sprężynę, oto fragment, który zrobi to za mnie zrobić to w pliku @Configuration

private @Inject RequestMappingHandlerAdapter adapter; 

@PostConstruct 
public void prioritizeCustomArgumentMethodHandlers() { 
    List<HandlerMethodArgumentResolver> argumentResolvers = 
     new ArrayList<> (adapter.getArgumentResolvers()); 
    List<HandlerMethodArgumentResolver> customResolvers = 
     adapter.getCustomArgumentResolvers(); 
    argumentResolvers.removeAll (customResolvers); 
    argumentResolvers.addAll (0, customResolvers); 
    adapter.setArgumentResolvers (argumentResolvers); 
} 
+0

Jak można to osiągnąć za pomocą konfiguracji XML? – Andy

+0

Nie musi to być "@ Konfiguracja", którą można umieścić na dowolnym pojedynczym komponencie, ale to hack.Nie musisz zmieniać całego projektu na java config, możesz mieć klasę z '@ Configuration' na swojej ścieżce automatycznego wykrywania, która właśnie to robi. Cała twoja inna konfiguracja byłaby w formacie XML. Alternatywnie, można rozszerzyć 'RequestMappingHandlerAdapter', umieścić tam ten kod (nie trzeba oczywiście oczywiście wstrzykiwać) i utworzyć komponent bean adaptera w formacie XML, jednak rozważyłbym podejście do czyszczenia konfiguracji, ponieważ w rzeczywistości konfigurowałeś adapter,

+0

Może zajść potrzeba wykonania innej konfiguracji niedostępnej przez XML i będziesz musiał umieścić ją w swojej klasie pochodnej, która stanie się miejscem, w którym zbierzesz wiele rzeczy, które nie mają ze sobą nic wspólnego. –

0

używam właściwość customArgumentResolvers załadować fasoli coś takiego:

<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"> 
     <property name="messageConverters"> 
      <list> 
       <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
        <property name="supportedMediaTypes"> 
         <list> 
          <value>text/html;charset=UTF-8</value> 
          <value>text/plain;charset=UTF-8</value> 
          <value>application/json;charset=UTF-8</value> 
         </list> 
        </property> 
       </bean> 
      </list> 
     </property> 
     <property name="customArgumentResolvers"> 
     <list> 
      <bean id="MyTestMethodArgumentResolver" class="com.gst.authorization.resolvers.MyTestMethodArgumentResolver"></bean>   
      <bean id="currentUserMethodArgumentResolver" class="com.gst.authorization.resolvers.CurrentUserMethodArgumentResolver"> 
          <property name="userModelClass" value="com.gst.model.appuser.AppUser" /> 
        <property name="userModelRepository" ref="userRepository" /> 
       </bean> 
     </list>   
     </property> 
    </bean> 
    <mvc:annotation-driven /> 
Powiązane problemy