当前位置: 首页 > 知识库问答 >
问题:

Jersey InputStream在Filter中被修改。无法确定如何访问泽西资源中已修改的inputStream

阙繁
2023-03-14

正如在如何使用Jersey拦截器获取请求主体中所讨论的,我正在修改ContainerRequestFilter中的EntityInputStream。

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  
}

但是,后来我不知道如何访问修改后的InputStream。我可以在资源中获得ServletContext,但我不知道如何获得我在过滤器中实际修改的对象ContainerRequest。

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

我被困在旧版本的球衣1.8上,所以我不确定这是否是问题的一部分。

共有1个答案

皇甫飞飙
2023-03-14

您所需要做的就是接受inputstream作为资源方法中的实体主体。如果需要ByteArrayInputStream,只需强制转换即可。

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

如果您还不知道,Jersey如何将请求流(用于请求正文)转换为Java类型(例如,JSON转换为POJO)是通过MessageBodyReader的。您可以在JAX-RS实体提供程序中了解更多关于它们的信息。

Jersey已经提供了一些易于转换的类型的标准阅读器,例如String。大多数内容类型可以转换为字符串。同样,它也有一个读取器来处理InputStream。这可能是最简单的转换,因为请求已经作为inputstream传入,所以阅读器所需要做的就是返回原始流,这就是传递给我们方法的内容。

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

下面是测试依赖项

<dependency>
    <groupId>com.sun.jersey.jersey-test-framework</groupId>
    <artifactId>jersey-test-framework-grizzly2</artifactId>
    <version>1.17.1</version>
    <scope>test</scope>
</dependency>
 类似资料:
  • 问题内容: 我正在尝试制作一个包含名称的列表。该列表应该是可修改的(添加,删除,排序等)。但是,每当我尝试更改ArrayAdapter中的项目时,程序都会崩溃,并显示错误。这是我的代码: 我尝试插入,删除和清除方法,但没有一个起作用。有人可以告诉我我做错了什么吗? 问题答案: 我自己尝试了一下…发现它没有用。所以我检查了ArrayAdapter的源代码并发现了问题。由数组初始化后,将其转换为不能修

  • Swift 5.x Set 访问和修改 1.遍历 Set 可以使用for-in遍历Set 因为Set是无序的, 如果要顺序遍历Set, 使用sorted()方法 let courses: Set = ["Math", "English", "History"] for course in courses { print(course) } print("--- 分割线 ---") for

  • 求你了,我需要你的帮助。每当我试图运行下面的程序时,它会说不兼容的类型,字符串不能转换为整数。

  • 问题内容: 我正在尝试将我的项目目录添加到GOPATH,在Linux中,我可以这样做 在〜/ .bashrc中 Powershell中的等效性是什么 问题答案: 这应该遵循您使用Powershell设置任何Environment变量的方式(如本文所述): 如果您希望它永久存在(即将来将适用于任何外壳程序): 需要注意的一件事:当我们用来创建新的用户或计算机级环境变量时,在Windows Power

  • 问题内容: 我需要在Java中更改JSON属性的值,我可以正确获取该值,但无法修改JSON。 这是下面的代码 做这个的最好方式是什么? 问题答案: 是不可变的,旨在进行解析操作。但是,可以将其转换为允许突变的(和): 对于数组,可以使用:

  • 问题内容: 有没有理由可以更改覆盖方法的访问修饰符?例如, 然后将package-private访问修饰符更改为, 我只是出于好奇而问这个问题。 问题答案: Java不允许您对access修饰符进行 更严格的限制 ,因为这会违反以下规则:子类实例应该可以代替超类实例使用。但是当涉及到 减少 访问限制时……好吧,也许超类是由另一个人编写的,他们没有想到您要使用其类的方式。 人们编写的程序以及编程时所