成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

java在filter中獲取POST請(qǐng)求中request參數(shù)以及解決ServletInputStre

OldPanda / 2473人閱讀

摘要:想要回去請(qǐng)求中的請(qǐng)求參數(shù),可以直接使用方法。流讀取錯(cuò)誤流關(guān)閉錯(cuò)誤這樣將獲取中的所有格式的參數(shù)信息??梢愿鶕?jù)需求,進(jìn)行驗(yàn)簽或校驗(yàn)等一系列操作。神奇此時(shí)的流已經(jīng)被讀取一次,相當(dāng)于已經(jīng)作廢,此時(shí)請(qǐng)求接口必然是報(bào)錯(cuò)的。

想要回去GET請(qǐng)求中的請(qǐng)求參數(shù),可以直接使用request.getParamMap()方法。但是POST請(qǐng)求的requestBody參數(shù)就必須使用流的方式來(lái)獲取。

            BufferedReader reader = null;
            String body = null;
            try {
                reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
                body = IOUtils.read(reader).replaceAll("	|
|
", "");
            } catch (IOException e) {
                logger.error("流讀取錯(cuò)誤:"+e);
                return;
            }finally {
                if (null != reader){
                    try {
                        reader.close();
                    } catch (IOException e) {
                        logger.error("流關(guān)閉錯(cuò)誤:"+e);
                    }
                }
            }
            Map paramMap = JSON.parseObject(body);

這樣將獲取body中的所有json格式的參數(shù)信息??梢愿鶕?jù)需求,進(jìn)行驗(yàn)簽或校驗(yàn)等一系列操作。但是當(dāng)我們chain.doFilter(request, response),驚喜的發(fā)現(xiàn)接口400了??!
WHAT??!!
嘿嘿o( ̄▽ ̄)d
我們都知道,讀取流的時(shí)候是有標(biāo)志的,讀取一次移動(dòng)一次,讀取到哪里,移動(dòng)到哪里,讀到最后,返回-1,表示讀取完成。再次讀取需要重置位置,但是ServletInputStream中是沒(méi)有重置方法的,也就是說(shuō)流只能被讀取一次。神奇??!Σ(⊙▽⊙"a 此時(shí)的流已經(jīng)被讀取一次,相當(dāng)于已經(jīng)作廢,此時(shí)請(qǐng)求接口必然是報(bào)錯(cuò)的。
行吧,你既然不讓我重復(fù)讀,那我就把你的流拿過(guò)來(lái)封裝成自己的流,這樣我想讀多少次就讀多少次!ψ(`?′)ψ
加入jar包:javax.servlet

        
        
            javax.servlet
            javax.servlet-api
            3.1.0
            provided
        

實(shí)現(xiàn)HttpServletRequestWrapper類

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.net.URLDecoder;
import java.util.*;

/**
 * @author zhoumin
 * @create 2018-10-31 16:13
 */
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
    private Map paramsMap;

    @Override
    public Map getParameterMap() {
        return paramsMap;
    }

    @Override
    public String getParameter(String name) {// 重寫(xiě)getParameter,代表參數(shù)從當(dāng)前類中的map獲取
        String[] values = paramsMap.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public String[] getParameterValues(String name) {// 同上
        return paramsMap.get(name);
    }

    @Override
    public Enumeration getParameterNames() {
        return Collections.enumeration(paramsMap.keySet());
    }

    private String getRequestBody(InputStream stream) {
        String line = "";
        StringBuilder body = new StringBuilder();
        int counter = 0;

        // 讀取POST提交的數(shù)據(jù)內(nèi)容
        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        try {
            while ((line = reader.readLine()) != null) {
                if (counter > 0) {
                    body.append("rn");
                }
                body.append(line);
                counter++;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return body.toString();
    }

    private HashMap getParamMapFromPost(HttpServletRequest request) {

        String body = "";
        try {
            body = getRequestBody(request.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        HashMap result = new HashMap();

        if (null == body || 0 == body.length()) {
            return result;
        }

        return parseQueryString(body);
    }

    // 自定義解碼函數(shù)
    private String decodeValue(String value) {
        if (value.contains("%u")) {
            return Encodes.urlDecode(value);
        } else {
            try {
                return URLDecoder.decode(value, "UTF-8");
            } catch (UnsupportedEncodingException e) {
                return "";// 非UTF-8編碼
            }
        }
    }

    public HashMap parseQueryString(String s) {
        String valArray[] = null;
        if (s == null) {
            throw new IllegalArgumentException();
        }
        HashMap ht = new HashMap();
        StringTokenizer st = new StringTokenizer(s, "&");
        while (st.hasMoreTokens()) {
            String pair = (String) st.nextToken();
            int pos = pair.indexOf("=");
            if (pos == -1) {
                continue;
            }
            String key = pair.substring(0, pos);
            String val = pair.substring(pos + 1, pair.length());
            if (ht.containsKey(key)) {
                String oldVals[] = (String[]) ht.get(key);
                valArray = new String[oldVals.length + 1];
                for (int i = 0; i < oldVals.length; i++) {
                    valArray[i] = oldVals[i];
                }
                valArray[oldVals.length] = decodeValue(val);
            } else {
                valArray = new String[1];
                valArray[0] = decodeValue(val);
            }
            ht.put(key, valArray);
        }
        return ht;
    }

    private Map getParamMapFromGet(HttpServletRequest request) {
        return parseQueryString(request.getQueryString());
    }

    private final byte[] body; // 報(bào)文

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        body = readBytes(request.getInputStream());

        // 首先從POST中獲取數(shù)據(jù)
        if ("POST".equals(request.getMethod().toUpperCase())) {
            paramsMap = getParamMapFromPost(this);
        } else {
            paramsMap = getParamMapFromGet(this);
        }

    }

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

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

            @Override
            public int read() throws IOException {
                return bais.read();
            }

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

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

            @Override
            public void setReadListener(ReadListener arg0) {

            }
        };
    }

    private static byte[] readBytes(InputStream in) throws IOException {
        BufferedInputStream bufin = new BufferedInputStream(in);
        int buffSize = 1024;
        ByteArrayOutputStream out = new ByteArrayOutputStream(buffSize);

        byte[] temp = new byte[buffSize];
        int size = 0;
        while ((size = bufin.read(temp)) != -1) {
            out.write(temp, 0, size);
        }
        bufin.close();

        byte[] content = out.toByteArray();
        return content;
    }

}

解碼

/**
     * URL 解碼, Encode默認(rèn)為UTF-8.
     */
    public static String urlDecode(String part) {
        try {
            return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
        } catch (UnsupportedEncodingException e) {
            throw new InvalidTokenException(part);
        }
    }

那么上面讀取參數(shù)的代碼修改為:

             ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(
                    (HttpServletRequest) request);
            BufferedReader reader = null;
            String body = null;
            try {
                reader = new BufferedReader(new InputStreamReader(requestWrapper.getInputStream()));
                body = IOUtils.read(reader).replaceAll("	|
|
", "");
            } catch (IOException e) {
                logger.error("流讀取錯(cuò)誤:"+e);
                return;
            }finally {
                if (null != reader){
                    try {
                        reader.close();
                    } catch (IOException e) {
                        logger.error("流關(guān)閉錯(cuò)誤:"+e);
                    }
                }
            }
            Map paramMap = JSON.parseObject(body);
            .
            .
            .
            chain.doFilter(requestWrapper, response);

OK!又是打醬油的一天。(づ??????)づ

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/71971.html

相關(guān)文章

  • JavaWEB開(kāi)發(fā)15——Listener&Listener

    摘要:創(chuàng)建與銷毀對(duì)象是發(fā)送請(qǐng)求服務(wù)器就會(huì)創(chuàng)建它,當(dāng)響應(yīng)產(chǎn)生時(shí),對(duì)象就會(huì)銷毀。是容器為開(kāi)發(fā)人員提供的對(duì)象,它提供了對(duì)某一資源的已過(guò)濾請(qǐng)求調(diào)用鏈的視圖。 一、Listener監(jiān)聽(tīng)器 Javaweb開(kāi)發(fā)中的監(jiān)聽(tīng)器,是用于監(jiān)聽(tīng)web常見(jiàn)對(duì)象 HttpServletRequest HttpSession ServletContext 監(jiān)聽(tīng)它們的創(chuàng)建與銷毀 屬性變化 session綁...

    RebeccaZhong 評(píng)論0 收藏0
  • cors跨域之簡(jiǎn)單請(qǐng)求與預(yù)檢請(qǐng)求(發(fā)送請(qǐng)求頭帶令牌token)

    摘要:所以跨域請(qǐng)求分兩種簡(jiǎn)單請(qǐng)求和預(yù)檢請(qǐng)求。但對(duì)于第二個(gè)錯(cuò)誤,好像沒(méi)法向第一種那樣,將預(yù)檢請(qǐng)求轉(zhuǎn)變?yōu)楹?jiǎn)單請(qǐng)求,所以,只有尋找方法怎么在后端實(shí)現(xiàn)相應(yīng)的預(yù)檢請(qǐng)求,來(lái)返回一個(gè)狀態(tài)碼,告訴瀏覽器此次跨域請(qǐng)求可以繼續(xù)。 引子 自從從JAVA偽全棧轉(zhuǎn)前端以來(lái),學(xué)習(xí)的路上就充滿了荊棘(奇葩問(wèn)題),而涉及前后端分離這個(gè)問(wèn)題,對(duì)cors的應(yīng)用不斷增多,暴露出的問(wèn)題也接踵而至。這兩天動(dòng)手實(shí)踐基于Token的WE...

    zsy888 評(píng)論0 收藏0
  • cors跨域之簡(jiǎn)單請(qǐng)求與預(yù)檢請(qǐng)求(發(fā)送請(qǐng)求頭帶令牌token)

    摘要:所以跨域請(qǐng)求分兩種簡(jiǎn)單請(qǐng)求和預(yù)檢請(qǐng)求。但對(duì)于第二個(gè)錯(cuò)誤,好像沒(méi)法向第一種那樣,將預(yù)檢請(qǐng)求轉(zhuǎn)變?yōu)楹?jiǎn)單請(qǐng)求,所以,只有尋找方法怎么在后端實(shí)現(xiàn)相應(yīng)的預(yù)檢請(qǐng)求,來(lái)返回一個(gè)狀態(tài)碼,告訴瀏覽器此次跨域請(qǐng)求可以繼續(xù)。 引子 自從從JAVA偽全棧轉(zhuǎn)前端以來(lái),學(xué)習(xí)的路上就充滿了荊棘(奇葩問(wèn)題),而涉及前后端分離這個(gè)問(wèn)題,對(duì)cors的應(yīng)用不斷增多,暴露出的問(wèn)題也接踵而至。這兩天動(dòng)手實(shí)踐基于Token的WE...

    RaoMeng 評(píng)論0 收藏0
  • Java后端支付大雜燴之sps.controller(支付請(qǐng)求入口,配置文件)(五)

    摘要:重要的是學(xué)習(xí)過(guò)程,而不是結(jié)果。但,結(jié)果同樣重要,加油。。在這提一點(diǎn),由于網(wǎng)絡(luò)原因等異常情況支付平臺(tái)可能出現(xiàn)多次發(fā)送支付結(jié)果的情況,通知回調(diào)接口商戶要注意做好接口冪等,其余的不再多說(shuō)。 7、sps.controller.base,front. 說(shuō)明 如果有幸能看到,其實(shí)只為自己記錄,回頭復(fù)習(xí)用 1、本文項(xiàng)目來(lái)自Martin404,自己只是臨摹大佬的項(xiàng)目。 2、重要的是學(xué)習(xí)過(guò)程,而不是結(jié)...

    Joyven 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<