61.7. entity Writer Interceptor

61.7.1. 개요

이 섹션에서는 클라이언트 측 또는 서버 측에서 메시지 본문을 작성할 때 출력 스트림을 가로채는 데 사용할 수 있는 엔터티 작성기 인터셉터 를 구현하고 등록하는 방법을 설명합니다. 이는 일반적으로 암호화 및 암호 해독 또는 압축 해제와 같은 요청 본문의 일반적인 변환에 유용합니다.

61.7.2. WriterInterceptor 인터페이스

javax.ws.rs.ext.WriterInterceptor 인터페이스는 다음과 같이 정의됩니다.

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

public interface WriterInterceptor {
    void aroundWriteTo(WriterInterceptorContext context)
            throws java.io.IOException, javax.ws.rs.WebApplicationException;
}

WriterInterceptor 인터페이스를 구현하면 서버 쪽 또는 클라이언트 측에서 기록되는 메시지 본문(Entity object)을 가로챌 수 있습니다. 다음 컨텍스트 중 하나에서 엔터티 작성기 인터셉터를 사용할 수 있습니다.

  • 서버 측인터셉터로 바인딩된 경우, 엔터티 작성자 인터셉터는 응답을 마샬링하고 클라이언트로 다시 전송하기 직전에 응답 메시지 본문을 인터셉트합니다.
  • 클라이언트 쪽인터셉터로 바인딩된 경우 엔터티 작성자 인터셉터는 요청을 마샬링하고 서버로 전송하기 직전에 요청 메시지 본문을 인터셉트합니다.

61.7.3. WriterInterceptorContext 인터페이스

WriterInterceptoraroundWriteTo 방법은 javax.ws.rs.ext.WriterInterceptorContext 유형의 하나의 인수를 수신하며 메시지 본문(Entity object) 및 메시지 메타데이터 둘 다에 액세스하는 데 사용할 수 있습니다.

WriterInterceptorContext 인터페이스는 다음과 같이 정의됩니다.

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

import java.io.IOException;
import java.io.OutputStream;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;

public interface WriterInterceptorContext extends InterceptorContext {

    void proceed() throws IOException, WebApplicationException;

    Object getEntity();

    void setEntity(Object entity);

    OutputStream getOutputStream();

    public void setOutputStream(OutputStream os);

    MultivaluedMap<String, Object> getHeaders();
}

61.7.4. InterceptorContext 인터페이스

WriterInterceptorContext 인터페이스는 기본 InterceptorContext 인터페이스에서 상속된 메서드도 지원합니다. InterceptorContext 에 대한 정의는 “InterceptorContext 인터페이스” 에서 참조하십시오.

61.7.5. 클라이언트 측에서의 샘플 구현

클라이언트 측에 대해 엔터티 작성기 인터셉터를 구현하려면 WriterInterceptor 인터페이스를 구현하는 클래스를 정의합니다.

예를 들어 다음 코드는 클라이언트 쪽의 엔터티 작성기 인터셉터 예를 보여줍니다(우선 순위 10임)는 발신 요청의 메시지 본문에 추가 텍스트 행을 추가합니다.

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

import java.io.IOException;
import java.io.OutputStream;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import javax.annotation.Priority;

@Priority(value = 10)
public class SampleClientWriterInterceptor implements WriterInterceptor {

  @Override
  public void aroundWriteTo(WriterInterceptorContext interceptorContext)
          throws IOException, WebApplicationException {
    OutputStream outputStream = interceptorContext.getOutputStream();
    String appendedContent = "\nInterceptors always get the last word in.";
    outputStream.write(appendedContent.getBytes());
    interceptorContext.setOutputStream(outputStream);

    interceptorContext.proceed();
  }
}

61.7.6. 서버 측에서의 샘플 구현

서버 측에 대해 엔터티 작성자 인터셉터를 구현하려면 WriterInterceptor 인터페이스를 구현하고 @Provider 주석으로 주석을 추가하는 클래스를 정의합니다.

예를 들어 다음 코드는 서버 측의 엔터티 작성기 인터셉터 예를 보여줍니다(우선 순위 10임)는 발신 요청의 메시지 본문에 추가 텍스트 행을 추가합니다.

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

import java.io.IOException;
import java.io.OutputStream;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import javax.annotation.Priority;

@Priority(value = 10)
@Provider
public class SampleServerWriterInterceptor implements WriterInterceptor {

  @Override
  public void aroundWriteTo(WriterInterceptorContext interceptorContext)
          throws IOException, WebApplicationException {
    OutputStream outputStream = interceptorContext.getOutputStream();
    String appendedContent = "\nInterceptors always get the last word in.";
    outputStream.write(appendedContent.getBytes());
    interceptorContext.setOutputStream(outputStream);

    interceptorContext.proceed();
  }
}

61.7.7. 클라이언트 측에서 작성자 인터셉터 바인딩

JAX-RS 2.0 클라이언트 API를 사용하여 javax.ws.rs.client.Client 오브젝트 또는 javax.ws.client. WebTarget 오브젝트에 엔터티 작성자 인터셉터를 직접 등록할 수 있습니다. 사실상, 이는 작성자 인터셉터를 선택적으로 다른 범위에 적용할 수 있으므로 인터셉터의 특정 URI 경로만 영향을 받습니다.

예를 들어 다음 코드는 client 오브젝트를 사용하여 수행된 모든 호출에 적용되도록 SampleClientReaderInterceptor 인터셉터를 등록하는 방법을 보여줍니다.

// 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(SampleClientReaderInterceptor.class);

JAX-RS 2.0 클라이언트를 사용하여 인터셉터를 등록하는 방법에 대한 자세한 내용은 49.5절. “클라이언트 끝점 구성” 을 참조하십시오.

61.7.8. 서버 측에서 작성자 인터셉터 바인딩

서버 측의 작성자 인터셉터를 바인딩 하려면 (즉, Apache CXF 런타임에 설치) 다음 단계를 수행합니다.

  1. 다음 코드 조각에 표시된 대로 @Provider 주석을 writer 인터셉터 클래스에 추가합니다.

    // Java
    package org.jboss.fuse.example;
    ...
    import javax.ws.rs.WebApplicationException;
    import javax.ws.rs.ext.Provider;
    import javax.ws.rs.ext.WriterInterceptor;
    import javax.ws.rs.ext.WriterInterceptorContext;
    import javax.annotation.Priority;
    
    @Priority(value = 10)
    @Provider
    public class SampleServerWriterInterceptor implements WriterInterceptor {
      ...
    }

    작성자 인터셉터 구현이 Apache CXF 런타임에 로드되면 REST 구현에서 로드된 클래스를 자동으로 검사하여 @Provider 주석( 스캔 단계)으로 표시된 클래스를 검색합니다.

  2. XML에서 JAX-RS 서버 엔드포인트를 정의할 때(예: 18.1절. “JAX-RS Server 엔드 포인트 구성”참조), jaxrs:providers 요소의 공급자 목록에 writer 인터셉터를 추가합니다.

    <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="interceptorProvider" />
          </jaxrs:providers>
          <bean id="interceptorProvider" class="org.jboss.fuse.example.SampleServerWriterInterceptor"/>
    
        </jaxrs:server>
    
    </blueprint>
    참고

    이 단계는 Apache CXF의 비표준 요구 사항입니다. JAX-RS 표준에 따르면 @Provider 주석은 인터셉터를 바인딩하는 데 필요한 모든 주석이어야 합니다. 그러나 실제로는 표준 접근 방식은 다소 무독하며 많은 라이브러리가 대규모 프로젝트에 포함될 때 번들링 공급자로 이어질 수 있습니다.