61.8. 动态绑定
概述
将容器过滤器和容器拦截器绑定到资源的标准方法是使用 @Provider
注释标注过滤器和拦截器。这样可确保绑定是 全局 :即,过滤器和拦截器绑定到服务器端的每个资源类和资源方法。
动态绑定是绑定服务器端的替代方法,可让您选取并选择要将拦截器和过滤器应用到哪些资源方法。要为过滤器和拦截器启用动态绑定,您必须实施自定义 DynamicFeature
接口,如下所述。
DynamicFeature 接口
DynamicFeature
接口在 javax.ws.rx.container
软件包中定义,如下所示:
// Java package javax.ws.rs.container; import javax.ws.rs.core.FeatureContext; import javax.ws.rs.ext.ReaderInterceptor; import javax.ws.rs.ext.WriterInterceptor; public interface DynamicFeature { public void configure(ResourceInfo resourceInfo, FeatureContext context); }
实施动态功能
您实现动态功能,如下所示:
-
按照前面所述,实施一个或多个容器过滤器或容器拦截器。但是,不要 给他们标上
@Provider
注释(否则,会为他们全局绑定,使动态功能无效)。 -
通过实施
DynamicFeature
类,覆盖配置
方法来创建您自己的动态功能。 -
在配置
方法中,您可以使用resourceInfo
参数来发现哪些资源类以及哪个资源方法被调用。您可以使用这些信息来决定是否注册一些过滤器或拦截器。 -
如果您决定使用当前资源方法注册过滤器或拦截器,可以通过调用其中一个
context.register
方法来实现。 -
记得使用
@Provider
注释给您的动态功能类标注,以确保在部署的扫描阶段获取该类。
动态功能示例
以下示例演示了如何定义动态功能,为使用 @GET
标注的 MyResource
类(或子类)的任何方法注册 LoggingFilter
过滤器:
// Java ... import javax.ws.rs.container.DynamicFeature; import javax.ws.rs.container.ResourceInfo; import javax.ws.rs.core.FeatureContext; import javax.ws.rs.ext.Provider; @Provider public class DynamicLoggingFilterFeature implements DynamicFeature { @Override void configure(ResourceInfo resourceInfo, FeatureContext context) { if (MyResource.class.isAssignableFrom(resourceInfo.getResourceClass()) && resourceInfo.getResourceMethod().isAnnotationPresent(GET.class)) { context.register(new LoggingFilter()); } }
动态绑定进程
JAX-RS 标准要求通过 DynamicFeature.configure
方法 为每一资源方法调用一次。这意味着,每个资源方法都可能安装有过滤器或拦截器,但动态功能最多可以决定每个情况下都会注册过滤器或拦截器。换句话说,动态功能支持的绑定的粒度是单个资源方法的级别。
FeatureContext 接口
FeatureContext
接口(允许您在配置方法中注册过滤器和拦截器)被定义为 Configurable
<> 的子接口,如下所示:
// Java package javax.ws.rs.core; public interface FeatureContext extends Configurable<FeatureContext> { }
Configurable&
lt;> 接口定义了在单一资源方法上注册过滤器和拦截器的方法,如下所示:
// Java ... package javax.ws.rs.core; import java.util.Map; public interface Configurable<C extends Configurable> { public Configuration getConfiguration(); public C property(String name, Object value); public C register(Class<?> componentClass); public C register(Class<?> componentClass, int priority); public C register(Class<?> componentClass, Class<?>... contracts); public C register(Class<?> componentClass, Map<Class<?>, Integer> contracts); public C register(Object component); public C register(Object component, int priority); public C register(Object component, Class<?>... contracts); public C register(Object component, Map<Class<?>, Integer> contracts); }