在 SpringSecurity 的自定義登錄攔截中,使用了 jackson 去獲取請求流解析成實體類實例對象。如:
// 登錄是否含手機號
User voUser = new ObjectMapper().readValue(req.getInputStream(), User.class); if (voUser == null || voUser.getPhoneNum() == null) { throw new AuthenticationServiceException("請輸入手機號"); }
Jackson已經研究了一下,看這篇:SpringSecurity登錄報錯403問題:com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field異常、及 Jackson 的使用
所以接下來了解一下:req.getInputStream() 這個知識。
一、編碼方式:"multipart/form-data"
瀏覽器采用了一種編碼方式,即 "multipart/form-data" 的編碼方式,采用這種方式,瀏覽器可以很容易將表單內的數據和文件放在一起發送。
這種編碼方式先定義好一個不可能在數據中出現的字符串作為分界符,然后用它將各個數據段分開,而對於每個數據段都對應着 HTML 頁面表單中的一個 Input 區,包括一個 content-disposition 屬性,說明了這個數據段的一些信息,如果這個數據段的內容是一個文件,還會有 Content-Type 屬性,然后就是數據本身。
我們可以用request.getInputStream()或request.getReader()得到提交的數據,但想要得到文件內容,還需要我們自己解析。
二、request.getInputStream()接參流程
1、spring接到瀏覽器傳來的post請求所傳進來的參數都在request里
@RequestMapping(value = PROXY_URL, method = RequestMethod.POST, produces = PRODUCES) public Object proxy(final HttpServletRequest request, final HttpServletResponse response) { String json = new String(readInputStream(request.getInputStream()), "UTF-8"); }
此時debug查看request.getInputStream()的值是全部請求信息,但是並非我們想要是參數
所以我們要對結果解析:readInputSream()是解析方法
2、結果解析
public static byte[] readInputStream(InputStream inStream) throws Exception { ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; boolean var3 = false; int len; while((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); return outSteam.toByteArray(); }
inStream.read(buffer)讀取數據賦值給buffer
outSteam的結果就是我們想要的數據了。
注意:這里的json格式的數據是前端定義好傳進來的,和后台對 IO 流的解析無關。
關於 IO 流的基礎知識可以看這篇博客:Java里的IO基礎知識筆記:IO流、字節流/字符流、File對象讀取、輸入流/輸出流(使用過后及時關閉、緩沖區)、Filter模式、ZIP操作、讀取classpath資源的意義、序列化/反序列化、Reader/Writer、使用Files工具類及其局限性