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

有時候我們需要到攔截器中做下參數(shù)的預處理钧萍,如危險字符過濾粘茄、權限判斷碗啄、打印請求參數(shù)日志 等操作。
以前使用url中以振峻?和& 拼接或使用form-data等傳參形式都沒有問題公般。 而現(xiàn)在參數(shù)都以contentType="application/json;charset=utf-8" 的形式放到了request Body中弛秋,如果我們提前去拿一次,那么等程序運行到controller中時參數(shù)已經(jīng)是為空再也獲取不到了俐载。所以我們得想辦法解決這個問題蟹略。

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

  • 定義類屬性HttpServletRequest遏佣,this.request保存request的引用挖炬。
  • 定義類屬性byte[] requestBody, 在重寫的getInputStream方法中使用IOUtils.copy將輸入流轉輸出流再轉 byte[]状婶,然后進行賦值意敛。
  • 最后構造一個ByteArrayInputStream 返回馅巷。這樣就不會影響原來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請求對象
        private HttpServletRequest request;

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

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

            /**
             * 關鍵一步钓猬,自己構造 ServletInputStream。沒有這一部分后面再從request拿出來的參數(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對象傳入 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);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市综膀,隨后出現(xiàn)的幾起案子澳迫,更是在濱河造成了極大的恐慌,老刑警劉巖剧劝,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橄登,死亡現(xiàn)場離奇詭異,居然都是意外死亡讥此,警方通過查閱死者的電腦和手機拢锹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來萄喳,“玉大人面褐,你說我怎么就攤上這事∪√ィ” “怎么了展哭?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長闻蛀。 經(jīng)常有香客問我匪傍,道長,這世上最難降的妖魔是什么觉痛? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任役衡,我火速辦了婚禮,結果婚禮上薪棒,老公的妹妹穿的比我還像新娘手蝎。我一直安慰自己,他們只是感情好俐芯,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布棵介。 她就那樣靜靜地躺著,像睡著了一般吧史。 火紅的嫁衣襯著肌膚如雪邮辽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音吨述,去河邊找鬼岩睁。 笑死,一個胖子當著我的面吹牛揣云,可吹牛的內容都是我干的捕儒。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼邓夕,長吁一口氣:“原來是場噩夢啊……” “哼刘莹!你這毒婦竟也來了?” 一聲冷哼從身側響起翎迁,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎净薛,沒想到半個月后汪榔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡肃拜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年痴腌,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片燃领。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡士聪,死狀恐怖,靈堂內的尸體忽然破棺而出猛蔽,到底是詐尸還是另有隱情剥悟,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布曼库,位于F島的核電站区岗,受9級特大地震影響,放射性物質發(fā)生泄漏毁枯。R本人自食惡果不足惜慈缔,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望种玛。 院中可真熱鬧藐鹤,春花似錦、人聲如沸赂韵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祭示。三九已至括堤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背悄窃。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工讥电, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人轧抗。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓恩敌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親横媚。 傳聞我的和親對象是個殘疾皇子纠炮,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355