3 votes

Spring aliasFor pour les annotations avec Target(PARAMETER)

J'essaie d'utiliser la méta-annotation de spring en utilisant l'annotation aliasFor pour créer une annotation personnalisée pour les springs. RequestParam

Il suffit de "prolonger/remplacer".

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

   @AliasFor("name")
   String value() default "";

   ----
}

avec mon annotation

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

    @AliasFor(annotation = RequestParam.class, attribute = "name")
    String name() default "";

    @AliasFor(annotation = RequestParam.class, attribute = "required")
    boolean required() default false;

    @AliasFor(annotation = RequestParam.class, attribute = "defaultValue")
    String defaultValue() default ValueConstants.DEFAULT_NONE;

}

De cette façon, il lance l'exception

org.springframework.core.annotation.AnnotationConfigurationException:   @AliasFor declaration on attribute [name] in annotation [package.QueryParam] declares an alias for attribute [name] in meta-annotation [org.springframework.web.bind.annotation.RequestParam] which is not meta-present.

Le problème est que sans la RequestParam annotée sur la QueryParam, cela ne fonctionne pas. Et il n'est pas possible de mettre la RequestParam comme PARAMÈTRE ciblé.

@RequestParam <--This is not possible. 
public @interface QueryParam

Existe-t-il un autre moyen d'y parvenir ?

4voto

Babl Points 4686

Fondamentalement, ce que vous voulez réaliser n'est pas possible maintenant, du moins pour la version 4.3.3 de Spring. Il y a deux problèmes principaux, le premier est le fait que les annotations comme @RequestParam sont déclarés avec @Target(ElementType.PARAMETER) ce qui rend impossible son utilisation dans le cadre de méta-annotations. De plus, Spring MVC recherche les annotations sur les paramètres des méthodes à l'aide de la fonction org.springframework.core.MethodParameter.getParameterAnnotations() qui ne prend pas en charge les méta-annotations ou les annotations composées. Mais si vous avez vraiment besoin de personnalisations à cet endroit, vous pouvez utiliser HandlerMethodArgumentResolver au lieu des annotations méta.

Votre code ressemblera donc à quelque chose comme

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

   String name() default "";

   boolean required() default false;

   String defaultValue() default ValueConstants.DEFAULT_NONE;

}

Ensuite, en utilisant le HandlerMethodArgumentResolver ajoutez la logique personnalisée dont vous avez besoin.

public class QueryParamResolver implements HandlerMethodArgumentResolver {

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

   public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest,
        WebDataBinderFactory binderFactory) throws Exception {
       QueryParam attr = parameter.getParameterAnnotation(QueryParam.class);
       // here you can use any logic which you need
       return webRequest.getParameter(attr.value());
   }
}

Ensuite, nous devons enregistrer notre HandlerMethodArgumentResolver

@Configuration
@EnableWebMvc
public class Config extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
      argumentResolvers.add(new QueryParamResolver());
    }
}

Et enfin, utilisons notre annotation personnalisée

 @GetMapping("/test")
 public String test(@QueryParam("foo") String foo){
      // something here 
 }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X