springboot项目无法获取form-urlencoded类型的报文体

最近springmvc项目升级成springboot,发现以前已经接入的一个系统向重构后的项目发送请求时,项目无法从HttpRequest中获取报文体。在springmvc项目中通过request.getInputStream();方式获取报文体,在springboot中得到inputstream是null,用@RequestBody注解也同样获取不到报文。用request.getParameterMap()确能获取到key是,value是"1.0" encoding="UTF-8" ?>...的表单,说明项目将报文按照表单的格式进行了分隔。

使用抓包软件对发送过来的报文抓包进行分析之后发现,发来的http请求报文头里面设置了Content-type 为x-www-form-urlencoded,然而我们需要解析的是xml报文。


抓包的报文头部分

经排查是一个HiddenHttpMethodFilter的过滤器去获取了parameterMap,如下图所示:
HiddenHttpMethodFilter

解决方案:
1、 禁用这个filter

    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new HiddenHttpMethodFilter();
    }
    @Bean
    public FilterRegistrationBean disableSpringBootHiddenHttpMethodFilter(HiddenHttpMethodFilter filter) {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setEnabled(false);
        return filterRegistrationBean;
    }

2、重写这个filter

    @Bean
    public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
        return new OrderedHiddenHttpMethodFilter(){
            @Override
            protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                    throws ServletException, IOException {
                filterChain.doFilter(request, response);
            }
        };
    }

一般按照以上两种方式就可以获取xml报文了,但是我发现使用了我们公司的日志框架之后,还是获取不到xml报文,看了我司的自动打印收发日志的框架之后发现了如下的代码:


InputStreamWrapper

都是先获取表单,再获取报文体,于是需要自己加一个过滤器,针对这个路径先获取报文体,创建自己的过滤器,并且注册到FilterRegistrationBean,代码如下:

@Configuration
public class FilterConfiguration {
    
    @Bean
    public FilterRegistrationBean requestBodyFilter() {
        FilterRegistrationBean filterRegistrationBean = new
                FilterRegistrationBean(new RequestBodyFilter());
        filterRegistrationBean.setDispatcherTypes(REQUEST);
        filterRegistrationBean.setName("inputStreamReplaceServletFilter");
//        filterRegistrationBean.setOrder(Ordered.HIGHEST_PRECEDENCE + 5);
        filterRegistrationBean.addUrlPatterns("/oc/charge");
        filterRegistrationBean.addUrlPatterns("/oc/query");
        return filterRegistrationBean;
    }
    
    
    class InputStreamReplacementHttpRequestWrapper extends HttpServletRequestWrapper {

        private String requestBody;

        private Map parameterMap;

        public InputStreamReplacementHttpRequestWrapper(HttpServletRequest request)
            throws IOException {
                super(request);
                requestBody = StreamUtils.copyToString(request.getInputStream(), Constant.DEFAULT_CHARSET);
                parameterMap = new HashMap(request.getParameterMap());
                parameterMap.put("ocxmldata", new String[] {requestBody});
            }
            
            public String getRequestBody() {
                return requestBody;
            }
            
            @Override
            public ServletInputStream getInputStream() throws IOException {
                ByteArrayInputStream is = new ByteArrayInputStream(
                        requestBody.getBytes(Constant.DEFAULT_CHARSET_NAME));
                return new ServletInputStream() {
                    @Override
                    public int read() throws IOException {
                        return is.read();
                    }
                    
                    @Override
                    public boolean isFinished() {
                        return is.available() <= 0;
                    }
                    
                    @Override
                    public boolean isReady() {
                        return true;
                    }
                    
                    @Override
                    public void setReadListener(ReadListener listener) {
                    
                    }
                };
            }
            
            @Override
            public BufferedReader getReader() throws IOException {
                return new BufferedReader(new InputStreamReader(getInputStream()));
            }
            
            @Override
            public String getParameter(String name) {
                String[] values = parameterMap.get(name);
                if (values != null) {
                    if(values.length == 0) {
                        return "";
                    }
                    return values[0];
                } else {
                    return null;
                }
            }
            
            @Override
            public Map getParameterMap() {
                return parameterMap;
            }
            
            @Override
            public Enumeration getParameterNames() {
                return Collections.enumeration(parameterMap.keySet());
            }
            
            @Override
            public String[] getParameterValues(String name) {
                return parameterMap.get(name);
            }
        }
    
    
    class RequestBodyFilter implements Filter {

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
//            System.out.println("init RequestBodyFilter");
        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            // TODO Auto-generated method stub
//          System.out.println("doFilter RequestBodyFilter");
            HttpServletRequest req = (HttpServletRequest) request;
            request = new InputStreamReplacementHttpRequestWrapper(req);
            chain.doFilter(request, response);
        }

        @Override
        public void destroy() {
            // TODO Auto-generated method stub

        }

    }
}

你可能感兴趣的:(springboot项目无法获取form-urlencoded类型的报文体)