使用注释写入 Jersey 中的 ServletContext。

Writing into ServletContext in Jersey using annotation.

我有一个 class 这样的:

   public class MyResource(){

       public MyResource(@Context ServletContext context){
            context.setAttribute("someAttribute","someVal");
       }

       @PUT
       public void someMethod(){
         ...
       }
   }

我想使用注解(即 JAX-RS/Jersey 读取注解的值并将其写入 ServletContext,这样我就可以在其他地方访问这个值,在请求范围内注入 ServletContext。 )

@MyCustomAnnotation(name="someVal")
public class MyResource(){


}

注解需要一些代码处理。

您需要创建一个过滤器,在调用您的方法之前处理您的自定义注释。

见:https://jersey.java.net/documentation/latest/filters-and-interceptors.html

创建过滤器应该相当容易,但这还不够。它会被调用,但不知道它会在什么上下文中被调用。根据上下文,我的意思是 class / 方法将在过滤器执行后立即被调用。在此示例中,我假设您的注释(称为 MyCustomAnnotation)可以应用于 class / 方法。

为此,您需要创建一个 "Dynamic Feature" 来为每个可能的上下文绑定不同的过滤器实例。

详情:

对于给定的 JAX-RS class:

@MyCustomAnnotation(name="someVal")
class MyClass{

    @GET
    @MyCustomAnnotation(name="someConfig")
    public Object myMethod(){
    ...
    }

    @GET
    @MyCustomAnnotation(name="otherConfig")
    public Object myOtherMethod(){
    ...
    }

}

首先,创建注释(我猜你知道,但只是为了清楚):

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation {

    String name() default "";

}

然后,创建一个过滤器。 注意特殊的构造函数。将为每个可能的上下文创建一个不同的过滤器实例。过滤器的正确实例将在特定上下文中使用。这样它将知道在什么情况下 (Class / Method) 被调用。这样,使用 intro-spectation,您的过滤器可以根据您在目标 class and/or 方法上使用的注释按您喜欢的方式运行:

@Priority(Priorities.AUTHORIZATION - 1)
public class MyFilter implements ContainerRequestFilter {

    private final Class<?> _class;
    private final Method method;
    private MyCustomAnnotation classAnnotation;
    private MyCustomAnnotation methodAnnotation;

    public MyFilter(Class<?> _class, Method method) {

        this._class = _class;
        this.method = method;

        this.classAnnotation = _class.getAnnotation(MyCustomAnnotation.class);
        this.methodAnnotation = method.getAnnotation(MyCustomAnnotation.class);

    }

    @Override
    public void filter(ContainerRequestContext requestContext) {

        // your code goes here!

        // based on classAnnotation and/or methodAnnotation, 
        // add whatever you want to the requestContext

    }
}

好的,现在我们有了一个注解,一个处理这个注解的过滤器,现在我们需要动态绑定到 class / 被注解的方法

public class MyFilterDynamicFeature implements DynamicFeature {

    @Override
    public void configure(final ResourceInfo resourceInfo, final FeatureContext configuration) {

        //if the class or the method is annotated, bind a new instance of our filter to this method
        if(resourceInfo.getResourceClass().getAnnotation(MyCustomAnnotation.class)!=null || resourceInfo.getResourceMethod().getAnnotation(MyCustomAnnotation.class)!=null){            
            configuration.register(new MyFilter(resourceInfo.getResourceClass(), resourceInfo.getResourceMethod()));
        }

    }
}

在您的 JAX-RS 配置中...注册您的新 DynamicFeature

public class MyRestConfig extends ResourceConfig {

    public RestConfig() {

        // your configs...

        packages("com.yourpackage.rest");

        // ...

        // handle @MyCustomAnnotation annotations
        register(MyFilterDynamicFeature.class);

        // ...    
    }

}

我希望这是清楚的。回顾一下你需要做什么

  1. 创建您的注释
  2. 用你的注释注释你的 JAX-RS class/方法
  3. 创建一个过滤器来处理您的注释
  4. 创建一个动态功能,它将为每个不同的上下文绑定不同的过滤器实例(方法/class 组合,其中至少一个或另一个用您的注释进行注释)
  5. 在您的其余配置中注册动态功能

----更新--------

您应该能够在运行时注入资源信息,而不是使用动态功能

@Context
private ResourceInfo resourceInfo;