真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

攔截器如何獲取HttpServletRequest里body數(shù)據(jù)

這篇文章主要講解了“攔截器如何獲取HttpServletRequest里body數(shù)據(jù)”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“攔截器如何獲取HttpServletRequest里body數(shù)據(jù)”吧!

成都創(chuàng)新互聯(lián)-云計(jì)算及IDC服務(wù)提供商,涵蓋公有云、IDC機(jī)房租用、服務(wù)器托管德陽(yáng)、等保安全、私有云建設(shè)等企業(yè)級(jí)互聯(lián)網(wǎng)基礎(chǔ)服務(wù),服務(wù)熱線:028-86922220

一、問(wèn)題

通過(guò)在攔截器中獲取request中的json數(shù)據(jù),我們可以實(shí)現(xiàn)對(duì)參數(shù)進(jìn)行校驗(yàn)和改寫。問(wèn)題是參數(shù)只能在攔截器里獲取一次,往后在controller層就無(wú)法獲取數(shù)據(jù),提示body為空。

在網(wǎng)上查找資料后發(fā)現(xiàn),request的輸入流只能讀取一次,那么這是為什么呢?

那是因?yàn)榱鲗?duì)應(yīng)的是數(shù)據(jù),數(shù)據(jù)放在內(nèi)存中,有的是部分放在內(nèi)存中。
read 一次標(biāo)記一次當(dāng)前位置(mark position),第二次read就從標(biāo)記位置繼續(xù)讀(從內(nèi)存中copy)數(shù)據(jù)。 所以這就是為什么讀了一次第二次是空了。 怎么讓它不為空呢?
只要inputstream 中的pos 變成0就可以重寫讀取當(dāng)前內(nèi)存中的數(shù)據(jù)。javaAPI中有一個(gè)方法public void reset() 這個(gè)方法就是可以重置pos為起始位置,但是不是所有的IO讀取流都可以調(diào)用該方法!
ServletInputStream是不能調(diào)用reset方法,這就導(dǎo)致了只能調(diào)用一次getInputStream()

二、解決辦法

HttpServletRequestWrapper是 httpServletRequest 的包裝類

新建一個(gè)類繼承HttpServletRequestWrapper實(shí)現(xiàn)對(duì) httpServletRequest 的裝飾,用來(lái)獲取 body 數(shù)據(jù)

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

再新建一個(gè) filter 實(shí)現(xiàn)對(duì)傳入的 httpServletRequest 的轉(zhuǎn)換

@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方法才對(duì)request進(jìn)行包裝
            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數(shù)據(jù)

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

經(jīng)測(cè)試發(fā)現(xiàn)并不影響controller層獲取body數(shù)據(jù)

為什么需要在 filter 里進(jìn)行對(duì) httpServletRequest 的包裝轉(zhuǎn)換,直接在攔截器里進(jìn)行包裝不行嘛?

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

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

    preHandle(request);

    service(request);
}

preHandler(Request request) {

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

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

    doFilter(request);
}

doFilter(Request request) {

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

    service(request);
}

感謝各位的閱讀,以上就是“攔截器如何獲取HttpServletRequest里body數(shù)據(jù)”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)攔截器如何獲取HttpServletRequest里body數(shù)據(jù)這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!


分享標(biāo)題:攔截器如何獲取HttpServletRequest里body數(shù)據(jù)
分享路徑:http://weahome.cn/article/gdojec.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部