天天看點

springmvc的參數接收不能相容以及HttpServletRequest中的流多次使用

web開發中的POST請求很常見,最近遇到的一個問題是寫接口,我看别人牛逼的接口都是又能浏覽器通路,又能JS通路,又能URL getUrl = new URL(url);URLConnection connection = getUrl.openConnection();通路,

而我在用springmvc的時候利用他請求參數自動封裝的用法,怎麼樣都不能相容JS和背景請求接口兩種用法,也是百度谷歌半天無果,最後我看我java發起的post請求,寫法如下:

OutputStream out = conn.getOutputStream();

out.write((jsonObj.toString()).getBytes("UTF-8"));

這就是輸出流,對于服務端來說就是要接收這個輸出流啊,springmvc的什麼表單或者json參數自動封裝成對象,或者各種接收參數的注解,其實都是封裝HttpServletRequest中的流。

既然這樣,那就不用springmvc的自動封裝了,自己封裝。

BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream(), "utf-8"));

StringBuffer sb = new StringBuffer("");

String temp;

while ((temp = br.readLine()) != null) {

sb.append(temp);

}

br.close();

這樣就能擷取到HttpServletRequest中的post資料了,sb.toString(),一般是json格式,至于json格式想得到對應類型的資料就很随意了。

這裡要注意的是:在正常開發中,HttpServletRequest這個參數需要經過多個過濾器,而無法保證在哪個過濾器的操作中被讀取了一次流的操作,隻能讀取一次,讀取了一次後面從過濾器到達controller的時候再擷取是null的。

那麼解決這個問題的辦法也有多個,這裡說一個算是比較簡單的做法

1、建立類:ThreadCache

public class ThreadCache {

// ThreadLocal裡隻存儲了簡單的String對象,也可以自己定義對象,存儲更加複雜的參數

private static ThreadLocal threadLocal = new ThreadLocal();

public static String getPostRequestParams() {

return threadLocal.get();

public static void setPostRequestParams(String postRequestParams) {

threadLocal.set(postRequestParams);

public static void removePostRequestParams() {

threadLocal.remove();

2、在過濾器中将以上讀取流的代碼進行改造一下

if ("POST".equals(req.getMethod().toUpperCase())) {

BufferedReader br = new BufferedReader(new InputStreamReader(

(ServletInputStream) request.getInputStream(), "utf-8"));

//将流放線上程裡面,在controller中需要重複利用,如果不這樣controller中request帶的post資料将會丢失

ThreadCache.setPostRequestParams(sb.toString());

3、到請求最終需要參數的地方擷取參數,比如springmvc中的controller裡面

String requestStr =  ThreadCache.getPostRequestParams();

requestStr 就是請求的json參數。