2015-09-17 20 views
8

Jak omówiono w artykule How to use Jersey interceptors to get request body, modyfikuję EntityInputStream w ContainerRequestFilter.Jersey InputStream jest modyfikowany w filtrze. Nie można dowiedzieć się, jak uzyskać dostęp do zmodyfikowanego inputStream w Jersey Resource

public filter(ContainerRequest request){ 
    ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    InputStream in = request.getEntityInputStream(); 
    try{ 
      Readerwriter.writeTo(in, out); 
      byte[] requestEntity = out.toByteArray(); 

      // DO SOMETHING WITH BYTES HERE 

      request.setEntityInputStream(new ByteArrayInputStream(requestEntity)); 

     }/// error handling code here 
} 

Później jednak nie wiem, jak uzyskać dostęp do zmodyfikowanego InputStream. Mogę uzyskać ServletContext w zasobie, ale nie mogę dowiedzieć się, jak dostać się do obiektu, który faktycznie zmodyfikowałem w filtrze, ContainerRequest.

Czy mogę zrobić coś takiego? Koszulka nie można uruchomić, gdy próbuję to:

@Post 
@Path("/test") 
public Response test(@Context ContainerRequest cr){ 
    // blah blah 
    return.... 
} 

błąd Jersey:

Missing dependecy dla metody publicznej javax.ws.rs.core.Response example.TestController.test (com.sun. jersey.spi.container.ContainerRequest), opatrzone adnotacją POST zasobu, przykład klasy.TestController, nie jest rozpoznawany jako poprawna metoda zasobów.

Utknąłem na starej wersji koszulki, 1.8, więc nie jestem pewien, czy to część problemu.

Odpowiedz

1

Wszystko, co musisz zrobić, to zaakceptować InputStream jako ciało jednostki w swojej metodzie zasobów. Jeśli chcesz, aby ByteArrayInputStream po prostu go rzuciłeś.

@POST 
public Response post(InputStream in) { 
    ByteArrayInputStream bin = (ByteArrayInputStream)in; 
} 

Jeśli jeszcze nie wiesz, jak Jersey przetwarza strumień życzenie (dla ciała żądanie) na typy Java (na przykład JSON do POJO) jest przez MessageBodyReader s. Możesz przeczytać więcej o nich na JAX-RS Entity Providers.

Jersey już jest wyposażony w kilka standardowych czytników dla typów łatwo wymienialnych, na przykład String. Większość typów treści można przekonwertować na ciąg. Podobnie ma czytnik do obsługi InputStream. Jest to prawdopodobnie najłatwiejsza konwersja, ponieważ żądanie przychodzi już jako InputStream, więc naprawdę wszystko, co musiałby zrobić czytelnik, to zwrócenie oryginalnego strumienia i to właśnie zostanie przekazane naszej metodzie.

Jeśli spojrzymy na implementację InputStreamProvider, widzimy, że tak właśnie się dzieje. The original stream is simply returned. A ponieważ filtr dzieje się przed czytnikami, czytnik po prostu zwraca strumień, który ustawiliśmy.

Powyżej znajduje się pełna przykład stosując Jersey Test Framework

public class StreamFilterTest extends JerseyTest { 

    public static class InputStreamFilter implements ContainerRequestFilter { 

     @Override 
     public ContainerRequest filter(ContainerRequest request) { 
      try { 
       ByteArrayOutputStream out = new ByteArrayOutputStream(); 
       InputStream in = request.getEntityInputStream(); 
       ReaderWriter.writeTo(in, out); 

       byte[] requestBytes = out.toByteArray(); 
       byte[] worldBytes = " World".getBytes(StandardCharsets.UTF_8); 
       byte[] newBytes = new byte[requestBytes.length + worldBytes.length]; 
       System.arraycopy(requestBytes, 0, newBytes, 0, requestBytes.length); 
       System.arraycopy(worldBytes, 0, newBytes, requestBytes.length, worldBytes.length); 

       request.setEntityInputStream(new ByteArrayInputStream(newBytes)); 
      } catch (IOException ex) { 
       Logger.getLogger(InputStreamFilter.class.getName()).log(Level.SEVERE, null, ex); 
       throw new RuntimeException(ex); 
      } 

      return request; 
     } 
    } 

    @Path("stream") 
    public static class StreamResource { 

     @POST 
     public String post(InputStream in) throws Exception { 
      ByteArrayInputStream bin = (ByteArrayInputStream) in; 
      StringWriter writer = new StringWriter(); 
      ReaderWriter.writeTo(new InputStreamReader(bin), writer); 
      return writer.toString(); 
     } 
    } 

    public static class AppConfig extends DefaultResourceConfig { 
     public AppConfig() { 
      super(StreamResource.class); 
      getContainerRequestFilters().add(new InputStreamFilter()); 
     } 
    } 

    @Override 
    public WebAppDescriptor configure() { 
     return new WebAppDescriptor.Builder() 
       .initParam(WebComponent.RESOURCE_CONFIG_CLASS, 
         AppConfig.class.getName()) 
       .build(); 
    } 

    @Test 
    public void should_return_hello_world() { 
     String response = resource().path("stream").post(String.class, "Hello"); 
     assertEquals("Hello World", response); 
    } 
} 

oto zależność Test

<dependency> 
    <groupId>com.sun.jersey.jersey-test-framework</groupId> 
    <artifactId>jersey-test-framework-grizzly2</artifactId> 
    <version>1.17.1</version> 
    <scope>test</scope> 
</dependency>