摘要:想要回去請求中的請求參數,可以直接使用方法。流讀取錯誤流關閉錯誤這樣將獲取中的所有格式的參數信息。可以根據需求,進行驗簽或校驗等一系列操作。神奇此時的流已經被讀取一次,相當于已經作廢,此時請求接口必然是報錯的。
想要回去GET請求中的請求參數,可以直接使用request.getParamMap()方法。但是POST請求的requestBody參數就必須使用流的方式來獲取。
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("流關閉錯誤:"+e); } } } MapparamMap = JSON.parseObject(body);
這樣將獲取body中的所有json格式的參數信息。可以根據需求,進行驗簽或校驗等一系列操作。但是當我們chain.doFilter(request, response),驚喜的發現接口400了!!
WHAT??!!
嘿嘿o( ̄▽ ̄)d
我們都知道,讀取流的時候是有標志的,讀取一次移動一次,讀取到哪里,移動到哪里,讀到最后,返回-1,表示讀取完成。再次讀取需要重置位置,但是ServletInputStream中是沒有重置方法的,也就是說流只能被讀取一次。神奇!!Σ(⊙▽⊙"a 此時的流已經被讀取一次,相當于已經作廢,此時請求接口必然是報錯的。
行吧,你既然不讓我重復讀,那我就把你的流拿過來封裝成自己的流,這樣我想讀多少次就讀多少次!ψ(`?′)ψ
加入jar包:javax.servlet
javax.servlet javax.servlet-api 3.1.0 provided
實現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,代表參數從當前類中的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提交的數據內容 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); } // 自定義解碼函數 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中獲取數據 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默認為UTF-8. */ public static String urlDecode(String part) { try { return URLDecoder.decode(part, DEFAULT_URL_ENCODING); } catch (UnsupportedEncodingException e) { throw new InvalidTokenException(part); } }
那么上面讀取參數的代碼修改為:
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("流關閉錯誤:"+e); } } } MapparamMap = JSON.parseObject(body); . . . chain.doFilter(requestWrapper, response);
OK!又是打醬油的一天。(づ??????)づ
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/71971.html
摘要:創建與銷毀對象是發送請求服務器就會創建它,當響應產生時,對象就會銷毀。是容器為開發人員提供的對象,它提供了對某一資源的已過濾請求調用鏈的視圖。 一、Listener監聽器 Javaweb開發中的監聽器,是用于監聽web常見對象 HttpServletRequest HttpSession ServletContext 監聽它們的創建與銷毀 屬性變化 session綁...
摘要:所以跨域請求分兩種簡單請求和預檢請求。但對于第二個錯誤,好像沒法向第一種那樣,將預檢請求轉變為簡單請求,所以,只有尋找方法怎么在后端實現相應的預檢請求,來返回一個狀態碼,告訴瀏覽器此次跨域請求可以繼續。 引子 自從從JAVA偽全棧轉前端以來,學習的路上就充滿了荊棘(奇葩問題),而涉及前后端分離這個問題,對cors的應用不斷增多,暴露出的問題也接踵而至。這兩天動手實踐基于Token的WE...
摘要:所以跨域請求分兩種簡單請求和預檢請求。但對于第二個錯誤,好像沒法向第一種那樣,將預檢請求轉變為簡單請求,所以,只有尋找方法怎么在后端實現相應的預檢請求,來返回一個狀態碼,告訴瀏覽器此次跨域請求可以繼續。 引子 自從從JAVA偽全棧轉前端以來,學習的路上就充滿了荊棘(奇葩問題),而涉及前后端分離這個問題,對cors的應用不斷增多,暴露出的問題也接踵而至。這兩天動手實踐基于Token的WE...
摘要:重要的是學習過程,而不是結果。但,結果同樣重要,加油。。在這提一點,由于網絡原因等異常情況支付平臺可能出現多次發送支付結果的情況,通知回調接口商戶要注意做好接口冪等,其余的不再多說。 7、sps.controller.base,front. 說明 如果有幸能看到,其實只為自己記錄,回頭復習用 1、本文項目來自Martin404,自己只是臨摹大佬的項目。 2、重要的是學習過程,而不是結...
閱讀 2417·2021-11-19 09:40
閱讀 3588·2021-10-12 10:12
閱讀 1895·2021-09-22 15:04
閱讀 2908·2021-09-02 09:53
閱讀 770·2019-08-29 11:03
閱讀 1129·2019-08-28 18:11
閱讀 1732·2019-08-23 15:28
閱讀 3584·2019-08-23 15:05