2017-10-18 7 views
1

Je veux limiter la valeur de la taille paginable maximale à 10 (valeur par exemple) et je peux le faire comme ça:Que se passe-t-il avec le résolveur d'arguments par défaut lorsque le résolveur personnalisé pour le même type est ajouté?

@Configuration 
public class MvcConfiguration extends WebMvcConfigurerAdapter { 

    @Override 
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) { 
     super.addArgumentResolvers(argumentResolvers); 
     PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver(); 
     resolver.setMaxPageSize(10); 
     argumentResolvers.add(resolver); 
    } 
} 

et delcare méthode du contrôleur comme celui-ci

@RequestMapping(name = "list") 
    public String listUsers(@PageableDefault(size = 5, page = 0) Pageable pageable) { 

En effet, cela fonctionnera , Je ne serai pas en mesure de définir la taille de la page à> 10, mais je suis curieux de savoir pourquoi? Qu'est-ce qui arrive au printemps créé PageableHandlerMethodArgumentResolver? Pourquoi cette instance est prise en compte et non celle par défaut? Après tout, je ne remplace pas les résolveurs ici, en ajoutant seulement un nouveau.

+0

Le 'HandlerMethodArgumentResolver' qui retourne' true' sur les 'supports (MethodParameter)' est utilisé pour résoudre le paramètre de la méthode. Si ce que vous avez ajouté renvoie 'true', c'est celui utilisé même si l'autre résolveur le supporte. Il doit y avoir quelque chose d'autre qui se passe ici, les résolveurs ajoutés par l'utilisateur peuvent être prioritaires ou Spring n'ajoute plus ses résolveurs prédéfinis si un résolveur du même type existe mais avec cela je ne suis pas sûr. Un seul résolveur fonctionne sur tous les paramètres de la méthode. –

Répondre

1

1. Phase de configuration

Lorsque vous étendez WebMvcConfigurerAdapter et ajoutez résolveurs personnalisés dans addArgumentResolvers, (sauter beaucoup de code de configuration) vous les ajoutez en fait RequestMappingHandlerAdapterRequestMappingHandlerAdapter haricot enregistre en interne la liste de tous les résolveurs, à condition lors de l'initialisation. (WebMvcConfigurationSupport). Après cela, ils sont combinés avec des résolveurs par défaut. Et comme vous pouvez le voir sur le source code, PageableHandlerMethodArgumentResolver ne fait pas partie de la liste des résolveurs par défaut, mais provient d'une classe de configuration. Et dans mon cas (capture d'écran ci-dessous) les classes de configuration fournissent spring-boot-starter-data-rest version différente de PageableHandler: HateoasPageableHandlerMethodArgumentResolver

2. résolveurs ordre

résolveurs personnalisés sont commandés Ones après intégrés (source). Donc, vérifions cela et appelons un contrôleur, mais mettez d'abord le point d'arrêt en RequestMappingHandlerAdapter.invokeHandlerMethod(). De là, nous pouvons voir l'état interne de RequestMappingHandlerAdapter

enter image description here

Je surligné résolveur personnalisé MyPageableHandlerMethodArgumentResolver, enregistré de la même manière que vous avez fait dans votre code question.

Et le code qui résout réellement les arguments est HandlerMethodArgumentResolverComposite. Il est simple boucle et cela signifie que le premier enregistré HandlerMethodArgumentResolver sera utilisé

for (HandlerMethodArgumentResolver methodArgumentResolver : this.argumentResolvers) 
    if (methodArgumentResolver.supportsParameter(parameter)) { 
     result = methodArgumentResolver; 
     this.argumentResolverCache.put(parameter, result); 
     break; 
    } 

Et comme vous pouvez le voir à partir du code source, le résultat est mis en cache et encore jamais réitérait pour le même type de paramètre.

+0

Donc, fondamentalement parlant, en ce moment, cela fonctionne par une coïncidence ai-je raison? - Comme l'ordre de traitement des classes '@ Configuration' n'est pas déterminé, il arrive que ma configuration soit prioritaire. – Antoniossss

+0

@Antoniossss Je pense que oui, chaque configuration a 'LOWEST_PRECEDENCE' par défaut, mais vous pouvez utiliser' @ Order' pour assurer la priorité de vos configurations personnalisées. Donc, lorsque 'List ' est auto-dirigé dans [DelegatingWebMvcConfiguration] (https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/ servlet/config/annotation/DelegatingWebMvcConfiguration.java # L48-L53), il est trié intérieurement selon «l'ordre» des haricots. – varren

+0

En ce qui concerne les résolveurs qui proviennent de la [SpringDataWebConfiguration] (https://github.com/spring-projects/spring-data-commons/blob/master/src/main/java/org/springframework/data/web/config/ SpringDataWebConfiguration.java # L138-L149), je pense, il est configuré de telle manière que si vous étendez à partir de cette classe, surchargez 'addArgumentResolvers' et n'appelez pas super comme' HateoasAwareSpringDataWebConfiguration' vous n'obtenez pas le "default" resolvers – varren