springboot 在controller層獲取Post請求中request.getInputStream的值
springboot 在controller層獲取Post請求中request.getInputStream的值
https://www.csdn.net/tags/Mtjacg1sMTYyOTAtYmxvZwO0O0OO0O0O.html
這個有點坑,首先request的流的獲取每個請求只能獲取一次,之後再通過getInputStream獲取流的時候就獲取不到資料了,還有getInputStream和getReader和getParameter都可以獲取輸入流資料,但是存在衝突,也就是三者只要有一個對request獲取了輸入流資訊,那麼其他的方法之後就獲取不到資料了。這就是springboot埋的一個小坑,那麼怎麼通過request獲得Post請求的body值呢?
首先直接在controller層直接寫肯定是獲取不到的,即使你自己覺得你是第一次獲取輸入流,其實不然,在springboot啟動的時候攔截器中也通過getParameter獲取過輸入流,導致後面沒辦法獲取輸入流
下面解決辦法:重寫HiddenHttpMethodFilter攔截器
我們先看下這個攔截器裡面的方法
-
@Override
-
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-
throws ServletException, IOException {
-
-
HttpServletRequest requestToUse = request;
-
-
if ("POST".equals(request.getMethod()) && request.getAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE) == null) {
-
String paramValue = request.getParameter(this.methodParam);
-
if (StringUtils.hasLength(paramValue)) {
-
requestToUse = new
HttpMethodRequestWrapper(request, paramValue);
-
}
-
}
-
-
filterChain.doFilter(requestToUse, response);
-
}
這個request.getParameter()看到了吧,就是它影響了後面獲取輸入流,我們自己重寫這個方法就好了,我自己是在這個重寫的方法裡將request的輸入流獲取然後直接用的,我貼下程式碼
-
import com.alibaba.fastjson.JSON;
-
import lombok.extern.slf4j.Slf4j;
-
import net.sf.json.JSONObject;
-
import org.springframework.boot.web.filter.OrderedHiddenHttpMethodFilter;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Configuration;
-
import org.springframework.web.filter.HiddenHttpMethodFilter;
-
-
import javax.servlet.FilterChain;
-
import javax.servlet.ServletException;
-
import javax.servlet.ServletInputStream;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
import java.io.BufferedReader;
-
import java.io.IOException;
-
import java.io.InputStreamReader;
-
-
@Slf4j
-
@Configuration
-
public class WebConfig {
-
@Bean
-
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
-
return new OrderedHiddenHttpMethodFilter() {
-
@Override
-
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
-
throws ServletException, IOException {
-
BufferedReader reader = new BufferedReader(
-
new InputStreamReader(request.getInputStream(), "UTF-8"));
-
String line;
-
String result = "";
-
while ((line = reader.readLine()) != null) {
-
result += line;
-
}
-
log.info("業務驗證提示資訊! URL={} 引數:{}", request.getRequestURL().toString(),JSON.toJSON(result));
-
filterChain.doFilter(request, response);
-
}
-
};
-
}
-
}
然後我說一下這個坑:
一:即使重寫的方法我們不用輸入流,再controller也沒辦法獲取post的輸入流,我自己測了好多次都是這樣,具體情況不清楚
二:即使將獲取的輸入流裝入session中,在controller中獲取session也會出錯,獲取不到值
三:關注我關注我
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
經過我的測試,我們發現這樣雖然能夠取到post輸入流,但是這樣之後cotroller用於接參的物件將取不到資料,會報request body is missing.那麼大家就別用這種方式取輸入流吧,通過aop去獲取輸入引數也應該行,我沒試過,但思路是對的!!!!