摘要:想要回去請求中的請求參數(shù),可以直接使用方法。流讀取錯誤流關(guān)閉錯誤這樣將獲取中的所有格式的參數(shù)信息。可以根據(jù)需求,進行驗簽或校驗等一系列操作。神奇此時的流已經(jīng)被讀取一次,相當(dāng)于已經(jīng)作廢,此時請求接口必然是報錯的。
想要回去GET請求中的請求參數(shù),可以直接使用request.getParamMap()方法。但是POST請求的requestBody參數(shù)就必須使用流的方式來獲取。
BufferedReader reader = null; String body = null; try { reader = new BufferedReader(new InputStreamReader(request.getInputStream())); body = IOUtils.read(reader).replaceAll(" | | ", ""); } catch (IOException e) { logger.error("流讀取錯誤:"+e); return; }finally { if (null != reader){ try { reader.close(); } catch (IOException e) { logger.error("流關(guān)閉錯誤:"+e); } } } MapparamMap = JSON.parseObject(body);
這樣將獲取body中的所有json格式的參數(shù)信息。可以根據(jù)需求,進行驗簽或校驗等一系列操作。但是當(dāng)我們chain.doFilter(request, response),驚喜的發(fā)現(xiàn)接口400了!!
WHAT??!!
嘿嘿o( ̄▽ ̄)d
我們都知道,讀取流的時候是有標(biāo)志的,讀取一次移動一次,讀取到哪里,移動到哪里,讀到最后,返回-1,表示讀取完成。再次讀取需要重置位置,但是ServletInputStream中是沒有重置方法的,也就是說流只能被讀取一次。神奇!!Σ(⊙▽⊙"a 此時的流已經(jīng)被讀取一次,相當(dāng)于已經(jīng)作廢,此時請求接口必然是報錯的。
行吧,你既然不讓我重復(fù)讀,那我就把你的流拿過來封裝成自己的流,這樣我想讀多少次就讀多少次!ψ(`?′)ψ
加入jar包:javax.servlet
javax.servlet javax.servlet-api 3.1.0 provided
實現(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 MapparamsMap; @Override public Map getParameterMap() { return paramsMap; } @Override public String getParameter(String name) {// 重寫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; // 報文 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("流讀取錯誤:"+e); return; }finally { if (null != reader){ try { reader.close(); } catch (IOException e) { logger.error("流關(guān)閉錯誤:"+e); } } } MapparamMap = JSON.parseObject(body); . . . chain.doFilter(requestWrapper, response);
OK!又是打醬油的一天。(づ??????)づ
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/71971.html
摘要:創(chuàng)建與銷毀對象是發(fā)送請求服務(wù)器就會創(chuàng)建它,當(dāng)響應(yīng)產(chǎn)生時,對象就會銷毀。是容器為開發(fā)人員提供的對象,它提供了對某一資源的已過濾請求調(diào)用鏈的視圖。 一、Listener監(jiān)聽器 Javaweb開發(fā)中的監(jiān)聽器,是用于監(jiān)聽web常見對象 HttpServletRequest HttpSession ServletContext 監(jiān)聽它們的創(chuàng)建與銷毀 屬性變化 session綁...
摘要:所以跨域請求分兩種簡單請求和預(yù)檢請求。但對于第二個錯誤,好像沒法向第一種那樣,將預(yù)檢請求轉(zhuǎn)變?yōu)楹唵握埱螅裕挥袑ふ曳椒ㄔ趺丛诤蠖藢崿F(xiàn)相應(yīng)的預(yù)檢請求,來返回一個狀態(tài)碼,告訴瀏覽器此次跨域請求可以繼續(xù)。 引子 自從從JAVA偽全棧轉(zhuǎn)前端以來,學(xué)習(xí)的路上就充滿了荊棘(奇葩問題),而涉及前后端分離這個問題,對cors的應(yīng)用不斷增多,暴露出的問題也接踵而至。這兩天動手實踐基于Token的WE...
摘要:所以跨域請求分兩種簡單請求和預(yù)檢請求。但對于第二個錯誤,好像沒法向第一種那樣,將預(yù)檢請求轉(zhuǎn)變?yōu)楹唵握埱螅裕挥袑ふ曳椒ㄔ趺丛诤蠖藢崿F(xiàn)相應(yīng)的預(yù)檢請求,來返回一個狀態(tài)碼,告訴瀏覽器此次跨域請求可以繼續(xù)。 引子 自從從JAVA偽全棧轉(zhuǎn)前端以來,學(xué)習(xí)的路上就充滿了荊棘(奇葩問題),而涉及前后端分離這個問題,對cors的應(yīng)用不斷增多,暴露出的問題也接踵而至。這兩天動手實踐基于Token的WE...
摘要:重要的是學(xué)習(xí)過程,而不是結(jié)果。但,結(jié)果同樣重要,加油。。在這提一點,由于網(wǎng)絡(luò)原因等異常情況支付平臺可能出現(xiàn)多次發(fā)送支付結(jié)果的情況,通知回調(diào)接口商戶要注意做好接口冪等,其余的不再多說。 7、sps.controller.base,front. 說明 如果有幸能看到,其實只為自己記錄,回頭復(fù)習(xí)用 1、本文項目來自Martin404,自己只是臨摹大佬的項目。 2、重要的是學(xué)習(xí)過程,而不是結(jié)...
閱讀 2410·2021-11-19 09:40
閱讀 3575·2021-10-12 10:12
閱讀 1884·2021-09-22 15:04
閱讀 2898·2021-09-02 09:53
閱讀 762·2019-08-29 11:03
閱讀 1122·2019-08-28 18:11
閱讀 1724·2019-08-23 15:28
閱讀 3580·2019-08-23 15:05