使用注释写入 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);
// ...
}
}
我希望这是清楚的。回顾一下你需要做什么
- 创建您的注释
- 用你的注释注释你的 JAX-RS class/方法
- 创建一个过滤器来处理您的注释
- 创建一个动态功能,它将为每个不同的上下文绑定不同的过滤器实例(方法/class 组合,其中至少一个或另一个用您的注释进行注释)
- 在您的其余配置中注册动态功能
----更新--------
您应该能够在运行时注入资源信息,而不是使用动态功能
@Context
private ResourceInfo resourceInfo;
我有一个 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);
// ...
}
}
我希望这是清楚的。回顾一下你需要做什么
- 创建您的注释
- 用你的注释注释你的 JAX-RS class/方法
- 创建一个过滤器来处理您的注释
- 创建一个动态功能,它将为每个不同的上下文绑定不同的过滤器实例(方法/class 组合,其中至少一个或另一个用您的注释进行注释)
- 在您的其余配置中注册动态功能
----更新--------
您应该能够在运行时注入资源信息,而不是使用动态功能
@Context
private ResourceInfo resourceInfo;