61.3. 容器响应过滤器
概述
本节介绍如何实施和注册 容器响应过滤器,该过滤器 用于截获服务器端的传出响应消息。容器响应过滤器可用于在响应消息中自动填充标头,通常可用于任何类型的通用响应处理。
ContainerResponseFilter 接口
javax.ws.rs.container.ContainerResponseFilter 接口定义如下:
// Java
...
package javax.ws.rs.container;
import java.io.IOException;
public interface ContainerResponseFilter {
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext)
throws IOException;
}
通过实施 ContainerResponseFilter,您可以为服务器端的 ContainerResponse 扩展点创建一个过滤器,它会在调用执行后过滤响应消息。
容器响应过滤器可让您访问请求消息(通过 requestContext 参数)和响应消息(通过 responseContext 消息),但在此阶段只能修改响应。
ContainerResponseContext 接口
ContainerResponseFilter 的过滤器 方法接收两个参数:参数是 javax.ws.rs.container.ContainerRequestContext (请参阅 “ContainerRequestContext 接口”一节),以及类型为 javax.ws.rs.container.ContainerResponseContext 的参数,可用于访问传出响应消息及其相关元数据。
ContainerResponseContext 接口定义如下:
// Java
...
package javax.ws.rs.container;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.net.URI;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.EntityTag;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.MessageBodyWriter;
public interface ContainerResponseContext {
public int getStatus();
public void setStatus(int code);
public Response.StatusType getStatusInfo();
public void setStatusInfo(Response.StatusType statusInfo);
public MultivaluedMap<String, Object> getHeaders();
public abstract MultivaluedMap<String, String> getStringHeaders();
public String getHeaderString(String name);
public Set<String> getAllowedMethods();
public Date getDate();
public Locale getLanguage();
public int getLength();
public MediaType getMediaType();
public Map<String, NewCookie> getCookies();
public EntityTag getEntityTag();
public Date getLastModified();
public URI getLocation();
public Set<Link> getLinks();
boolean hasLink(String relation);
public Link getLink(String relation);
public Link.Builder getLinkBuilder(String relation);
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);
}实现示例
要为 ContainerResponse 扩展点实施容器响应过滤器(即,在服务器端执行过滤器后执行过滤器),请定义一个实施 ContainerResponseFilter 接口的类。
例如,以下代码显示了在 ContainerResponse 扩展点中安装的简单容器响应过滤器示例,其优先级为 10:
// Java
package org.jboss.fuse.example;
import javax.annotation.Priority;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
@Provider
@Priority(value = 10)
public class SampleContainerResponseFilter implements ContainerResponseFilter {
public SampleContainerResponseFilter() {
System.out.println("SampleContainerResponseFilter starting up");
}
@Override
public void filter(
ContainerRequestContext requestContext,
ContainerResponseContext responseContext
)
{
// This filter replaces the response message body with a fixed string
if (responseContext.hasEntity()) {
responseContext.setEntity("New message body!");
}
}
}绑定服务器响应过滤器
要 绑定 服务器响应过滤器(即要将它安装到 Apache CXF 运行时中),请执行以下步骤:
将
@Provider注释添加到容器响应过滤器类,如以下代码片段所示:// Java package org.jboss.fuse.example; import javax.annotation.Priority; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerResponseContext; import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.ext.Provider; @Provider @Priority(value = 10) public class SampleContainerResponseFilter implements ContainerResponseFilter { ... }
当容器响应过滤器实施加载到 Apache CXF 运行时中时,REST 实施会自动扫描加载的类,以搜索标有
@Provider注释( 扫描阶段)。在 XML 中定义 JAX-RS 服务器端点(例如,请参阅 第 18.1 节 “配置 JAX-RS 服务器端点”)时,将服务器响应过滤器添加到
jaxrs:providers元素中的供应商列表中。<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs" xmlns:cxf="http://cxf.apache.org/blueprint/core" ... > ... <jaxrs:server id="customerService" address="/customers"> ... <jaxrs:providers> <ref bean="filterProvider" /> </jaxrs:providers> <bean id="filterProvider" class="org.jboss.fuse.example.SampleContainerResponseFilter"/> </jaxrs:server> </blueprint>注意此步骤是 Apache CXF 的非标准要求。根据 JAX-RS 标准,严格说,
@Provider注释应当是绑定过滤器所需的所有内容。但是在实践中,标准方法有些不灵活,当许多库包含在大型项目中时,可能会导致禁止提供程序。