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);
}

实施动态功能

您实现一个动态功能,如下所示:

  1. 实施一个或多个容器过滤器或容器拦截器,如前面所述。但不要@Provider 注释(否则为他们进行全局绑定,使动态功能有效到期)。
  2. 通过实施 DynamicFeature 类来创建您自己的动态功能,覆盖配置方法。
  3. 在配置 方法中,您可以使用 resourceInfo 参数来发现哪个资源类以及要调用哪些资源方法。您可以使用这些信息来决定一些过滤器或拦截器。
  4. 如果您决定使用当前资源方法注册过滤器或拦截器,您可以通过调用其中一个 context.register 方法来实现。
  5. 记得使用 @Provider 注释给动态功能类添加注解,以确保它在部署的扫描阶段被使用。

动态功能示例

以下示例演示了如何定义用于为 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);
}