Spring MVC 解决request.getInputStream(POST请求)只能读取一次问题(全局替换request)

直奔主题

  实现方法:

    SpringMVC是通过前端控制器(DispatcherServlet)接收请求进行请求转发的,所以可以从这里入手把request对象替换为自定义的request对象,从而解决request的输入流只能读取一次的问题.

  步骤:

    1..重写service方法,实现替换request操作

package org.XXX.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.XXX.request.CustomRequest;

public class DispatcherServlet extends org.springframework.web.servlet.DispatcherServlet {

    private static final long serialVersionUID = 6781076086037842254L;
    
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
        // 全局替换request对象
        super.service(new CustomRequest(request), response);
    }

}

 

      将我们自己的前端控制器配置到web.xml中

    <servlet>
        <servlet-name>springmvc</servlet-name>
        <!-- <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> -->
        <servlet-class>org.XXX.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

      至此request替换操作已经完成,下面进入重点.

  2.实现自己的HttpServletRequest

package org.XXX.request;

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

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.io.IOUtils;

/**
 * 自定义Request
 * 
 */
public class CustomRequest extends HttpServletRequestWrapper {

    private byte[] postBody;

    public CustomRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (postBody == null) {
            postBody = IOUtils.toByteArray(super.getInputStream());
        }

        return new CustomServletInputStream(postBody);
    }

    /**
     * 自定义ServletInputStream
     *
     */
    private static class CustomServletInputStream extends ServletInputStream {

        private final InputStream is;

        CustomServletInputStream(byte[] postBody) {
            if (postBody == null) {
                postBody = new byte[0];
            }
            this.is = new ByteArrayInputStream(postBody);
        }

        @Override
        public int read() throws IOException {
            return is.read();
        }

    }
}

      大功告成!!

    最后附上AOP方法中读取post内容的部分代码

            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            String requestBody = null;
            if ("POST".equals(request.getMethod())) {
                // 读取requestBody
                byte[] bytes = IOUtils.toByteArray(request.getInputStream());
                requestBody = new String(bytes,request.getCharacterEncoding());
            }else{
                Map<String,String[]> parameterMap = request.getParameterMap();
                if(parameterMap != null && !parameterMap.isEmpty()){
                    requestBody = gson.toJson(parameterMap);
                }
            }
            if (requestBody != null && !requestBody.isEmpty()) {
                logger.info("requestBody: " + requestBody);
            }

 

posted on 2019-03-23 11:14  GFuZan  阅读(1545)  评论(0编辑  收藏  举报

导航