二次讀取request body中的參數(shù)數(shù)據(jù)

有時(shí)候我們需要到攔截器中做下參數(shù)的預(yù)處理,如危險(xiǎn)字符過(guò)濾、權(quán)限判斷、打印請(qǐng)求參數(shù)日志 等操作。
以前使用url中以?和& 拼接或使用form-data等傳參形式都沒(méi)有問(wèn)題。 而現(xiàn)在參數(shù)都以contentType="application/json;charset=utf-8" 的形式放到了request Body中,如果我們提前去拿一次,那么等程序運(yùn)行到controller中時(shí)參數(shù)已經(jīng)是為空再也獲取不到了。所以我們得想辦法解決這個(gè)問(wèn)題。

如下先自定義一個(gè)Request類:RequestWrapper 繼承HttpServletRequestWrapper 。

  • 定義類屬性HttpServletRequest,this.request保存request的引用。
  • 定義類屬性byte[] requestBody, 在重寫的getInputStream方法中使用IOUtils.copy將輸入流轉(zhuǎn)輸出流再轉(zhuǎn) byte[],然后進(jìn)行賦值。
  • 最后構(gòu)造一個(gè)ByteArrayInputStream 返回。這樣就不會(huì)影響原來(lái)request的InputStream。
package org.szwj.ca.identityauthsrv.controller;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.apache.commons.io.IOUtils;

public class RequestWrapper extends HttpServletRequestWrapper {

        private final Logger logger = LoggerFactory.getLogger(RequestWrapper.class);

        //參數(shù)字節(jié)數(shù)組
        private byte[] requestBody;
        //Http請(qǐng)求對(duì)象
        private HttpServletRequest request;

        public RequestWrapper(HttpServletRequest request) throws IOException {
            super(request);
            this.request = request;
            getInputStream();
        }

        /**
         * @return
         * @throws IOException
         */
        @Override
        public ServletInputStream getInputStream() throws IOException {
            /**
             * 每次調(diào)用此方法時(shí)將數(shù)據(jù)流中的數(shù)據(jù)讀取出來(lái),然后再回填到InputStream之中
             * 解決通過(guò)@RequestBody和@RequestParam(POST方式)讀取一次后控制器拿不到參數(shù)問(wèn)題
             */
            if (null == this.requestBody) {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ServletInputStream inputStream = request.getInputStream();
                IOUtils.copy(inputStream, baos);
                this.requestBody = baos.toByteArray();
                baos.close();
                inputStream.close();
            }

            /**
             * 關(guān)鍵一步,自己構(gòu)造 ServletInputStream。沒(méi)有這一部分后面再?gòu)膔equest拿出來(lái)的參數(shù)還是空的
             */
            final ByteArrayInputStream bais = new ByteArrayInputStream(requestBody);
            return new ServletInputStream() {

                @Override
                public boolean isFinished() {
                    return false;
                }

                @Override
                public boolean isReady() {
                    return false;
                }

                @Override
                public void setReadListener(ReadListener listener) {

                }

                @Override
                public int read() {
                    int read = bais.read();
                    try {
                        bais.close();
                    } catch (IOException e) {
                        logger.error("bais.close() 異常", e);
                    }
                    return read;
                }
            };

        }

        public byte[] getRequestBody() {
            return requestBody;
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(this.getInputStream()));
        }

    }
}


編寫Filter,將自定義的RequestWrapper對(duì)象傳入 chain.doFilter。

@Component
@WebFilter(filterName = "proxyFilter", urlPatterns = {"/*"})
class ProxyFilter implements Filter {
    private static final Logger logger = LoggerFactory.getLogger(ProxyFilter.class);
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        try {
            ServletRequest requestWrapper = null;
            if (request instanceof HttpServletRequest) {
                requestWrapper = new RequestWrapper((HttpServletRequest) request);
            }
            if (requestWrapper == null) {
                chain.doFilter(request, response);
            } else {
                chain.doFilter(requestWrapper, response);
            }
        } catch (IOException e) {
            logger.error("ProxyFilter.doFilter 異常", e);
        } catch (ServletException e) {
            logger.error("ProxyFilter.doFilter 異常", e);
        }
    }
    @Override
    public void destroy() {
    }
}

在攔截器中使用如下

        @Override
        protected void service(HttpServletRequest servletRequest,
            HttpServletResponse servletResponse) throws ServletException, IOException {
            String msg = "";
            RequestWrapper requestWrapper = null;
            String relBizNo = "";
            if (servletRequest instanceof RequestWrapper) {
                requestWrapper = (RequestWrapper) servletRequest;
                byte[] requestBody = requestWrapper.getRequestBody();
                String body = new String(requestBody);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容