61.4. Client Request Filter

概述

本节介绍如何实施和注册客户端请求 过滤器,该过滤器 用于截获客户端端的传出请求消息。客户端请求过滤器通常用于处理标头,并可用于任何类型的通用请求处理。

ClientRequestFilter 接口

javax.ws.rs.client.ClientRequestFilter 接口定义如下:

// Java
package javax.ws.rs.client;
...
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientRequestContext;
...
public interface ClientRequestFilter {
    void filter(ClientRequestContext requestContext) throws IOException;
}

通过实施 ClientRequestFilter,您可以为客户端侧的 ClientRequest 扩展点创建一个过滤器,它会在将消息发送到服务器前过滤请求消息。

ClientRequestContext interface

ClientRequestFilter过滤器 方法接收一个类型为 javax.ws.rs.client.ClientRequestContext 的单个参数,可用于访问传出请求消息及其相关元数据。ClientRequestContext 接口定义如下:

// Java
...
package javax.ws.rs.client;

import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.ws.rs.core.Configuration;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.MessageBodyWriter;

public interface ClientRequestContext {

    public Object getProperty(String name);

    public Collection<String> getPropertyNames();

    public void setProperty(String name, Object object);

    public void removeProperty(String name);

    public URI getUri();

    public void setUri(URI uri);

    public String getMethod();

    public void setMethod(String method);

    public MultivaluedMap<String, Object> getHeaders();

    public abstract MultivaluedMap<String, String> getStringHeaders();

    public String getHeaderString(String name);

    public Date getDate();

    public Locale getLanguage();

    public MediaType getMediaType();

    public List<MediaType> getAcceptableMediaTypes();

    public List<Locale> getAcceptableLanguages();

    public Map<String, Cookie> getCookies();

    public boolean hasEntity();

    public Object getEntity();

    public Class<?> getEntityClass();

    public Type getEntityType();

    public void setEntity(final Object entity);

    public void setEntity(
            final Object entity,
            final Annotation[] annotations,
            final MediaType mediaType);

    public Annotation[] getEntityAnnotations();

    public OutputStream getEntityStream();

    public void setEntityStream(OutputStream outputStream);

    public Client getClient();

    public Configuration getConfiguration();

    public void abortWith(Response response);
}

实现示例

要对 ClientRequest 扩展点实施客户端请求过滤器(即,在发送请求消息前执行过滤器),请定义一个实现 ClientRequestFilter 接口的类。

例如,以下代码显示了在 ClientRequest 扩展点中安装的简单客户端请求过滤器示例,其优先级为 20:

// Java
package org.jboss.fuse.example;

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.annotation.Priority;

@Priority(value = 20)
public class SampleClientRequestFilter implements ClientRequestFilter {

  public SampleClientRequestFilter() {
    System.out.println("SampleClientRequestFilter starting up");
  }

  @Override
  public void filter(ClientRequestContext requestContext) {
    System.out.println("ClientRequestFilter.filter() invoked");
  }
}

中止调用

可以通过实施适当的客户端请求过滤器来中止客户端调用。例如,您可以实施客户端侧过滤器来检查请求是否正确格式化,如有必要,则中止请求。

以下测试代码 始终 中止请求,将 BAD_REQUEST HTTP 状态返回到客户端调用代码:

// Java
package org.jboss.fuse.example;

import javax.ws.rs.client.ClientRequestContext;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.annotation.Priority;

@Priority(value = 10)
public class TestAbortClientRequestFilter implements ClientRequestFilter {

  public TestAbortClientRequestFilter() {
    System.out.println("TestAbortClientRequestFilter starting up");
  }

  @Override
  public void filter(ClientRequestContext requestContext) {
    // Test filter: aborts with BAD_REQUEST status
    requestContext.abortWith(Response.status(Status.BAD_REQUEST).build());
  }
}

注册客户端请求过滤器

使用 JAX-RS 2.0 客户端 API,您可以直接在 javax.ws.rs.client.client .Client 对象或 javax.ws.rs.client.client.client .client.WebTarget 对象上直接注册客户端请求过滤器。实际上,这意味着客户端请求过滤器可以选择性地应用到不同的范围,以便只有某些 URI 路径受到过滤器的影响。

例如,以下代码演示了如何注册 SampleClientRequestFilter 过滤器,使其应用于使用 client 对象进行的所有调用;以及如何注册 TestAbortClientRequestFilter 过滤器,使其仅应用于 rest/TestAbortClientRequest 的子路径。

// Java
...
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
...
Client client = ClientBuilder.newClient();
client.register(new SampleClientRequestFilter());
WebTarget target = client
  .target("http://localhost:8001/rest/TestAbortClientRequest");
target.register(new TestAbortClientRequestFilter());