Spring aliasFor用于带有目标的注释(PARAMETER)

law*_*wal 4 java spring spring-mvc spring-annotations spring-boot

我正在尝试使用aliasFor批注使用spring的Meta批注为springs RequestParam创建自定义批注

只需“扩展/替换”

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

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

   ----
}
Run Code Online (Sandbox Code Playgroud)

加上我的注释

@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;

}
Run Code Online (Sandbox Code Playgroud)

这样就抛出了异常

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.
Run Code Online (Sandbox Code Playgroud)

问题在于,如果没有在QueryParam上注释RequestParam,这将无法正常工作。并且无法将RequestParam设置为PARAMETER目标。

@RequestParam <--This is not possible. 
public @interface QueryParam
Run Code Online (Sandbox Code Playgroud)

那么还有另一种方法可以实现这一目标吗?

Bab*_*abl 5

基本上,现在您想实现的目标是不可能的,至少对于Spring v 4.3.3而言,存在两个主要问题,第一个问题是这样的事实:@RequestParam声明了诸如这样的注释@Target(ElementType.PARAMETER),使得无法将其用作元注释的一部分。此外,Spring MVC在方法参数上查找注释,使用org.springframework.core.MethodParameter.getParameterAnnotations()该方法参数不支持元注释或组合注释。但是,如果您确实需要一些自定义设置,则可以使用它们HandlerMethodArgumentResolver来代替元注释。

所以你的代码看起来像

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

   String name() default "";

   boolean required() default false;

   String defaultValue() default ValueConstants.DEFAULT_NONE;

}
Run Code Online (Sandbox Code Playgroud)

然后使用HandlerMethodArgumentResolver添加所需的自定义逻辑。

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());
   }
}
Run Code Online (Sandbox Code Playgroud)

然后我们需要注册我们的 HandlerMethodArgumentResolver

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

最后,让我们使用自定义注释

 @GetMapping("/test")
 public String test(@QueryParam("foo") String foo){
      // something here 
 }
Run Code Online (Sandbox Code Playgroud)