61.3. 컨테이너 응답 필터
61.3.1. 개요
이 섹션에서는 서버 측에서 나가는 응답 메시지를 가로채는 데 사용되는 컨테이너 응답 필터 를 구현하고 등록하는 방법을 설명합니다. 컨테이너 응답 필터는 응답 메시지에 헤더를 자동으로 채우는 데 사용할 수 있으며 일반적으로 모든 종류의 일반 응답 필터에 사용할 수 있습니다.
61.3.2. 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
메시지를 통해) 모두에 액세스할 수 있지만 이 단계에서 응답만 수정할 수 있습니다.
61.3.3. ContainerResponseContext 인터페이스
ContainerResponseFilter
의 필터
방법은 javax.ws.rs.container.ContainerRequestContext
유형의 인수와 유형 javax.ws.rs.container.ContainerResponseContext
의 인수이며, 발신 응답 메시지 및 관련 메타데이터에 액세스하는 데 사용할 수 있는 두 가지 인수를 수신합니다. “ContainerRequestContext interface”
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); }
61.3.4. 샘플 구현
ContainerResponse
확장 포인트(즉, 서버 측에서 호출이 실행된 후 필터가 실행되는 컨테이너 응답 필터)를 구현하려면 ContainerResponseFilter
인터페이스를 구현하는 클래스를 정의합니다.
예를 들어 다음 코드는 우선 순위가 10인 ContainerResponse
확장 지점에 설치된 간단한 컨테이너 응답 필터의 예를 보여줍니다.
// 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!"); } } }
61.3.5. 서버 응답 필터 바인딩
서버 응답 필터(즉, 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 Server 엔드 포인트 구성”참조),
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
주석은 필터를 바인딩하는 데 필요한 모든 것이어야 합니다. 그러나 실제로는 표준 접근 방식은 다소 무독하며 많은 라이브러리가 대규모 프로젝트에 포함될 때 번들링 공급자로 이어질 수 있습니다.