亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

攔截器如何獲取HttpServletRequest里body數據

發布時間:2021-07-07 14:14:46 來源:億速云 閱讀:3293 作者:chen 欄目:大數據

這篇文章主要講解了“攔截器如何獲取HttpServletRequest里body數據”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“攔截器如何獲取HttpServletRequest里body數據”吧!

一、問題

通過在攔截器中獲取request中的json數據,我們可以實現對參數進行校驗和改寫。問題是參數只能在攔截器里獲取一次,往后在controller層就無法獲取數據,提示body為空。

在網上查找資料后發現,request的輸入流只能讀取一次,那么這是為什么呢?

那是因為流對應的是數據,數據放在內存中,有的是部分放在內存中。
read 一次標記一次當前位置(mark position),第二次read就從標記位置繼續讀(從內存中copy)數據。 所以這就是為什么讀了一次第二次是空了。 怎么讓它不為空呢?
只要inputstream 中的pos 變成0就可以重寫讀取當前內存中的數據。javaAPI中有一個方法public void reset() 這個方法就是可以重置pos為起始位置,但是不是所有的IO讀取流都可以調用該方法!
ServletInputStream是不能調用reset方法,這就導致了只能調用一次getInputStream()

二、解決辦法

HttpServletRequestWrapper是 httpServletRequest 的包裝類

新建一個類繼承HttpServletRequestWrapper實現對 httpServletRequest 的裝飾,用來獲取 body 數據

public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {


    private final byte[] body;
    private String bodyStr;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        String bodyString = getBodyString(request);
        body = bodyString.getBytes(Charset.forName("UTF-8"));
        bodyStr=bodyString;
    }

    public String getBodyStr() {
        return bodyStr;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);

        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }

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

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

            @Override
            public void setReadListener(ReadListener readListener) {
            }
        };
    }


    public  String getBodyString(HttpServletRequest request) throws IOException {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        BufferedReader reader = null;
        try {
            inputStream = request.getInputStream();
            reader = new BufferedReader(
                    new InputStreamReader(inputStream, Charset.forName("UTF-8")));

            char[] bodyCharBuffer = new char[1024];
            int len = 0;
            while ((len = reader.read(bodyCharBuffer)) != -1) {
                sb.append(new String(bodyCharBuffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return sb.toString();
    }
}

再新建一個 filter 實現對傳入的 httpServletRequest 的轉換

@WebFilter(filterName = "httpServletRequestWrapperFilter", urlPatterns = {"/*"})
public class HttpServletRequestWrapperFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        ServletRequest requestWrapper = null;

        if (request instanceof HttpServletRequest) {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            //遇到post方法才對request進行包裝
            String methodType = httpRequest.getMethod();
            if ("POST".equals(methodType)) {
                requestWrapper = new BodyReaderHttpServletRequestWrapper(
                        (HttpServletRequest) request);
            }
        }
        if (null == requestWrapper) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }

    @Override
    public void destroy() {

    }
}

最后在攔截器就可以獲取request中body數據

 if(request instanceof  BodyReaderHttpServletRequestWrapper ){
            System.out.println(((BodyReaderHttpServletRequestWrapper) request).getBodyStr());
        }

經測試發現并不影響controller層獲取body數據

為什么需要在 filter 里進行對 httpServletRequest 的包裝轉換,直接在攔截器里進行包裝不行嘛?

過濾器(Filter)和攔截器(Interceptor)之間的最大區別就是,過濾器可以包裝Request和Response,而攔截器并不能

用代碼描述攔截器和過濾器的流程大概就是這樣的:
攔截器:void run () {
    Request request = new Request();

    preHandle(request);

    service(request);
}

preHandler(Request request) {

    request = new RequestWrapper(request);  //在這里修改Request的引用,不會影響到service方法的request
}

過濾器void run () {
    Request request = new Request();

    doFilter(request);
}

doFilter(Request request) {

    request = new RequestWrapper(request);  //在這里修改Request的引用,會影響到service方法的request

    service(request);
}

感謝各位的閱讀,以上就是“攔截器如何獲取HttpServletRequest里body數據”的內容了,經過本文的學習后,相信大家對攔截器如何獲取HttpServletRequest里body數據這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

固原市| 抚顺县| 资中县| 花莲县| 东平县| 盱眙县| 黎平县| 甘孜县| 共和县| 杭州市| SHOW| 海南省| 台州市| 平遥县| 宜昌市| 静海县| 五家渠市| 南和县| 象山县| 南川市| 成都市| 冷水江市| 揭东县| 合江县| 福贡县| 呈贡县| 凤庆县| 江安县| 绥棱县| 喀什市| 苍溪县| 南汇区| 楚雄市| 兴隆县| 天门市| 宁河县| 揭东县| 彰武县| 湘阴县| 昌宁县| 股票|