InputStream 在 MessageBodyReader Jersey 中提供空数据

Posted

技术标签:

【中文标题】InputStream 在 MessageBodyReader Jersey 中提供空数据【英文标题】:InputStream giving null data in MessageBodyReader Jersey 【发布时间】:2017-04-13 18:06:23 【问题描述】:

我正在尝试在泽西岛的 MessageBodyReader 中阅读 APPLICATION_FORM_URLENCODED。当我尝试使用 BufferedReader 读取流时,该流返回空数据

这是我的代码:

@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public class EmployeeReader implements MessageBodyReader<Employee> 

    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, 
        MediaType mediaType) 
        return true;
    

    @Override
    public Employee readFrom(Class<Employee> type, Type genericType, Annotation[] annotations, 
        MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
        throws IOException, WebApplicationException 
        System.out.println(entityStream.available());  //Prints 0
        BufferedReader br = new BufferedReader(new InputStreamReader(entityStream));
        String data = br.readLine();
        System.out.println("Stream Read:"+data);
        //data is null here
        .....
    

我可以看到数据是从我的 POST 请求中的表单以application/x-www-form-urlencoded 发送的,但是我无法在我的MessageBodyReader 中读取它。

在调试时,我可以看到 ByteChunk 保存了以下数据:

POST /Employees/employee HTTP/1.1
host:localhost:80800
connection:keep-alivee
content-length:144
postman-token:cf873d98-3208-292c-8fc1-6da8138a31faa
cache-control:no-cachee
origin:chrome-extension://fhbjgbiflinjbdggehcddcbncdddomopp
user-agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/54.0.2840.99 Safari/537.366
content-type:application/x-www-form-urlencodedd
accept:*/**
accept-encoding:gzip, deflate, brr
accept-language:en-US,en;q=0.88

id=3&name=Test

更新

我刚刚发现这是SpringBootServletInitializer 的某种副作用。禁用此功能会导致上述代码正常工作。

有人可以帮忙吗?

【问题讨论】:

POST 参数作为请求参数到达 servlet,而不是作为消息体。 @EJP 我在独立的 Jersey 应用程序中看到了 Jersey 2.5 的相同代码,此代码在带有 Spring Boot 的 Jersey 2.23 中不起作用,此外,正如我在问题中提到的那样,我可以看到调试控制台中 InputStream 的 ByteChunk 中的数据(发布在问题中)(id=3&amp;name=Test 【参考方案1】:

显然有一个HiddenHttpMethodFilter 在请求到达表单数据代码和POST 请求之前执行getParameter。所以InputStream 已经被读取并且br.readLine(); 正在返回null

我在其他帖子之一here 中找到了一种方法来覆盖它

@Configuration
public class FilterConfig  
    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() 
        return new HiddenHttpMethodFilter() 
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                    FilterChain filterChain) throws ServletException, IOException 
                if ("POST".equals(request.getMethod())
                        && request.getContentType().equals(MediaType.APPLICATION_FORM_URLENCODED)) 
                    //Skip this filter and call the next filter in the chain.
                    filterChain.doFilter(request, response);
                 else 
                    //Continue with processing this filter.
                    super.doFilterInternal(request, response, filterChain);
                
            
        ;
    

所以它的作用只是检查请求是否为POST 类型以及MediaType 是否为APPLICATION_FORM_URLENCODED,如果是,则我们跳过过滤器链的这一部分,否则对于我们处理此过滤器的所有其他请求也是。

这样InputStream到达MessageBodyReader时就不会被读取

【讨论】:

我遇到了类似的问题,它是由 spring-mvc 5 的内置请求日志记录引起的,请参阅 ***.com/a/59264125/3656774

以上是关于InputStream 在 MessageBodyReader Jersey 中提供空数据的主要内容,如果未能解决你的问题,请参考以下文章

AngularJS textarea 换行符/换行符转换

如何在不读取 InputStream 的情况下检查 InputStream 是不是为空?

如何在 Java 中将 String[] 数组转换为 InputStream

我可以在同一个程序中同时使用使用 InputStream 的 Scanner 和 inputstream 本身吗?

将 InputStream 写入文件 [重复]

我需要在 Java 中关闭 InputStream 吗?