61.6. 엔터티 리더 인터셉터

61.6.1. 개요

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

61.6.2. readerInterceptor 인터페이스

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

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

public interface ReaderInterceptor {
    public Object aroundReadFrom(ReaderInterceptorContext context)
            throws java.io.IOException, javax.ws.rs.WebApplicationException;
}

ReaderInterceptor 인터페이스를 구현하면 서버 측 또는 클라이언트 측에서 읽을 수 있으므로 메시지 본문(Entity 개체)을 가로챌 수 있습니다. 다음 컨텍스트 중 하나에서 엔터티 리더 인터셉터를 사용할 수 있습니다.

  • 서버 측인터셉터로 바인딩된 경우 엔터티 리더 인터셉터는 애플리케이션 코드(일치 일치하는 리소스에서)에서 액세스할 때 요청 메시지 본문을 가로챌 수 있습니다. REST 요청의 의미 체계에 따라 메시지 본문은 일치하는 리소스에서 액세스하지 못할 수 있습니다. 이 경우 리더 인터셉터가 호출되지 않습니다.
  • 클라이언트 측인터셉터로 바인딩된 경우 엔터티 리더 인터셉터는 클라이언트 코드에서 액세스할 때 응답 메시지 본문을 가로챌 수 있습니다. 클라이언트 코드가 응답 메시지에 명시적으로 액세스하지 않는 경우(예: Response.getEntity 메서드를 호출하여), 리더 인터셉터는 호출되지 않습니다.

61.6.3. ReaderInterceptorContext 인터페이스

ReaderInterceptoraroundReadFrom 메서드는 메시지 본문(Entity 개체) 및 메시지 메타데이터 모두에 액세스하는 데 사용할 수 있는 javax.ws.rs.ext. CryostatInterceptorContext 유형의 하나의 인수를 수신합니다.

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

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

import java.io.IOException;
import java.io.InputStream;

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

public interface ReaderInterceptorContext extends InterceptorContext {

    public Object proceed() throws IOException, WebApplicationException;

    public InputStream getInputStream();

    public void setInputStream(InputStream is);

    public MultivaluedMap<String, String> getHeaders();
}

61.6.4. InterceptorContext 인터페이스

ReaderInterceptorContext 인터페이스는 기본 InterceptorContext 인터페이스에서 상속된 메서드도 지원합니다.

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

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

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;

import javax.ws.rs.core.MediaType;

public interface InterceptorContext {

    public Object getProperty(String name);

    public Collection<String> getPropertyNames();

    public void setProperty(String name, Object object);

    public void removeProperty(String name);

    public Annotation[] getAnnotations();

    public void setAnnotations(Annotation[] annotations);

    Class<?> getType();

    public void setType(Class<?> type);

    Type getGenericType();

    public void setGenericType(Type genericType);

    public MediaType getMediaType();

    public void setMediaType(MediaType mediaType);
}

61.6.5. 클라이언트 측의 샘플 구현

클라이언트 측에 대한 엔터티 리더 인터셉터를 구현하려면 ReaderInterceptor 인터페이스를 구현하는 클래스를 정의합니다.

예를 들어 다음 코드는 클라이언트 측에 대한 엔터티 리더 인터셉터의 예를 보여줍니다(우선 순위 10으로 사용).이 예제에서는 들어오는 응답의 메시지 본문에서 knative _NAME 의 모든 인스턴스를 Red Hat 으로 대체합니다.

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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.Priority;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;

@Priority(value = 10)
public class SampleClientReaderInterceptor implements ReaderInterceptor {

  @Override
  public Object aroundReadFrom(ReaderInterceptorContext interceptorContext)
          throws IOException, WebApplicationException
  {
    InputStream inputStream = interceptorContext.getInputStream();
    byte[] bytes = new byte[inputStream.available()];
    inputStream.read(bytes);
    String responseContent = new String(bytes);
    responseContent = responseContent.replaceAll("COMPANY_NAME", "Red Hat");
    interceptorContext.setInputStream(new ByteArrayInputStream(responseContent.getBytes()));

    return interceptorContext.proceed();
  }
}

61.6.6. 서버 측의 샘플 구현

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

예를 들어 다음 코드는 서버 측에 대한 엔터티 리더 인터셉터의 예를 보여줍니다(우선 순위 10으로 사용).이 예제에서는 들어오는 요청의 메시지 본문에서 knative _NAME 의 모든 인스턴스를 Red Hat 으로 대체합니다.

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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.Priority;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;

@Priority(value = 10)
@Provider
public class SampleServerReaderInterceptor implements ReaderInterceptor {

  @Override
  public Object aroundReadFrom(ReaderInterceptorContext interceptorContext)
          throws IOException, WebApplicationException {
    InputStream inputStream = interceptorContext.getInputStream();
    byte[] bytes = new byte[inputStream.available()];
    inputStream.read(bytes);
    String requestContent = new String(bytes);
    requestContent = requestContent.replaceAll("COMPANY_NAME", "Red Hat");
    interceptorContext.setInputStream(new ByteArrayInputStream(requestContent.getBytes()));

    return interceptorContext.proceed();
  }
}

61.6.7. 클라이언트 측에서 리더 인터셉터 바인딩

Cryostat-RS 2.0 클라이언트 API를 사용하여 javax.ws.rs.client.Client 개체 또는 javax.ws.rs.client.client .WebTarget 오브젝트에 직접 엔터티 리더 인터셉터를 등록할 수 있습니다. 효과적으로, 이는 독자 인터셉터가 선택적으로 다른 범위에 적용되어 특정 URI 경로만 인터셉터의 영향을 받을 수 있음을 의미합니다.

예를 들어 다음 코드는 클라이언트 개체를 사용하여 만든 모든 호출에 적용되도록 SampleClient CryostatInterceptor 인터셉터를 등록하는 방법을 보여줍니다.

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

Cryostat-RS 2.0 클라이언트에 인터셉터 등록에 대한 자세한 내용은 49.5절. “클라이언트 끝점 구성” 에서 참조하십시오.

61.6.8. 서버 측에서 리더 인터셉터 바인딩

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

  1. 다음 코드 조각에 표시된 것처럼 reader interceptor 클래스에 @Provider 주석을 추가합니다.

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

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

  2. XML에서 Cryostat-RS 서버 끝점을 정의할 때(예: 18.1절. “Cryostat-RS 서버 끝점 구성”참조) jaxrs:providers 요소의 공급자 목록에 reader interceptor를 추가합니다.

    <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.SampleServerReaderInterceptor"/>
    
        </jaxrs:server>
    
    </blueprint>
    참고

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