想要回去GET請求中的請求參數,能夠直接使用request.getParamMap()方法。可是POST請求的requestBody參數就必須使用流的方式來獲取。java
BufferedReader reader = null; String body = null; try { reader = new BufferedReader(new InputStreamReader(request.getInputStream())); body = IOUtils.read(reader).replaceAll("\t|\n|\r", ""); } catch (IOException e) { logger.error("流讀取錯誤:"+e); return; }finally { if (null != reader){ try { reader.close(); } catch (IOException e) { logger.error("流關閉錯誤:"+e); } } } Map<String,Object> paramMap = JSON.parseObject(body);
這樣將獲取body中的全部json格式的參數信息。能夠根據需求,進行驗籤或校驗等一系列操做。可是當咱們chain.doFilter(request, response),驚喜的發現接口400了!!
WHAT??!!
嘿嘿o( ̄▽ ̄)d
咱們都知道,讀取流的時候是有標誌的,讀取一次移動一次,讀取到哪裏,移動到哪裏,讀到最後,返回-1,表示讀取完成。再次讀取須要重置位置,可是ServletInputStream中是沒有重置方法的,也就是說流只能被讀取一次。神奇!!Σ(⊙▽⊙"a 此時的流已經被讀取一次,至關於已經做廢,此時請求接口必然是報錯的。
行吧,你既然不讓我重複讀,那我就把你的流拿過來封裝成本身的流,這樣我想讀多少次就讀多少次!ψ(`∇´)ψ
加入jar包:javax.servletjson
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
實現HttpServletRequestWrapper類api
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<String, String[]> paramsMap; @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<String, String[]> getParamMapFromPost(HttpServletRequest request) { String body = ""; try { body = getRequestBody(request.getInputStream()); } catch (IOException e) { e.printStackTrace(); } HashMap<String, String[]> result = new HashMap<String, String[]>(); 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<String, String[]> parseQueryString(String s) { String valArray[] = null; if (s == null) { throw new IllegalArgumentException(); } HashMap<String, String[]> ht = new HashMap<String, String[]>(); 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<String, String[]> 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; } }
解碼app
/** * 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); } }
那麼上面讀取參數的代碼修改成:ide
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("\t|\n|\r", ""); } catch (IOException e) { logger.error("流讀取錯誤:"+e); return; }finally { if (null != reader){ try { reader.close(); } catch (IOException e) { logger.error("流關閉錯誤:"+e); } } } Map<String,Object> paramMap = JSON.parseObject(body); . . . chain.doFilter(requestWrapper, response);
OK!又是打醬油的一天。(づ。◕ᴗᴗ◕。)づ函數