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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM