欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot通過請求對象獲取輸入流無數(shù)據(jù)

 更新時間:2022年03月18日 09:01:01   作者:蔣固金  
這篇文章主要介紹了使用SpringBoot通過請求對象獲取輸入流無數(shù)據(jù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

請求對象獲取輸入流無數(shù)據(jù)問題

昨天下午在開發(fā)的時候遇到了奇怪的事情,在SpringBoot的Controller里面直接使用HttpServletRequest的getInputStream()方法的時候獲得的輸入流無數(shù)據(jù),通過getContentLength()獲得內(nèi)容長度的時候又是有值的,由于昨天比較晚了就沒有研究,今天花了點(diǎn)時間查一下原因。

出現(xiàn)這種情況,首先懷疑輸入流已經(jīng)被使用了,由于請求輸入流是不帶緩存的,使用一次后流就無效了,通常觸發(fā)解析輸入流就是調(diào)用了getParameter()等方法,經(jīng)過檢查代碼確認(rèn)沒有做過相關(guān)處理,所以懷疑SpringBoot底層做了處理。

查了一下SpringBoot的自動裝配配置,在WebMvcAutoConfiguration中初始化了一個OrderedHiddenHttpMethodFilter,默認(rèn)這個過濾器是生效的,相關(guān)代碼如下:

@Bean
@ConditionalOnMissingBean(HiddenHttpMethodFilter.class)
@ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled", matchIfMissing = true)
public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() {
? ? return new OrderedHiddenHttpMethodFilter();
}

OrderedHiddenHttpMethodFilter繼承了OrderedHiddenHttpMethodFilter,而OrderedHiddenHttpMethodFilter又繼承了HiddenHttpMethodFilter,在該類的doFilterInternal()方法中發(fā)現(xiàn)有對參數(shù)做處理,相關(guān)代碼如下:

@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)) {
? ? ? ? ? ? String method = paramValue.toUpperCase(Locale.ENGLISH);
? ? ? ? ? ? if (ALLOWED_METHODS.contains(method)) {
? ? ? ? ? ? ? ? requestToUse = new HttpMethodRequestWrapper(request, method);
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? filterChain.doFilter(requestToUse, response);
}

至此就可以定位問題的所在了,找到了問題下面就來看看如何解決。

方案一:禁用默認(rèn)的過濾器

SpringBoot在自動裝配的時候注入了OrderedHiddenHttpMethodFilter,如果我們不需要該功能,在配置文件中顯示的將其設(shè)置為false。配置如下:

spring.mvc.hiddenmethod.filter.enabled=false

方案二:使用@RequestBody注解

在需要獲取請求輸入流的方法上添加字節(jié)數(shù)組的參數(shù),并添加@RequestBody注解,示例代碼如下:

@RequestMapping("/**")
public 返回值 方法名(@RequestBody byte[] body) {
? ?// ...
}

方案三:自定義HiddenHttpMethodFilter過濾器

參考代碼如下:

@Bean
public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
? ? return new OrderedHiddenHttpMethodFilter(){
? ? ? ? @Override
? ? ? ? protected void doFilterInternal(HttpServletRequest request,
? ? ? ? ? ? HttpServletResponse response, FilterChain filterChain)
? ? ? ? ? ? throws ServletException, IOException {
? ? ? ? ? ? filterChain.doFilter(request, response);
? ? ? ? }
? ? };

request輸入流重復(fù)可讀

自定義類繼承 HttpServletRequestWrapper

/**
?* @describe 目的是讓其輸入流可重復(fù)讀
?* @author czx
?* @date 2020年5月15日22:53:35
?*/
@Slf4j
public class RequestWrapper extends HttpServletRequestWrapper {
? ? /**
? ? ?* 存儲body數(shù)據(jù)的容器
? ? ?*/
? ? private final byte[] body;
?
? ? public RequestWrapper(HttpServletRequest request) throws IOException {
? ? ? ? super(request);
?
? ? ? ? // 將body數(shù)據(jù)存儲起來
? ? ? ? String bodyStr = getBodyString(request);
? ? ? ? body = bodyStr.getBytes(Charset.defaultCharset());
? ? }
?
? ? /**
? ? ?* 獲取請求Body
? ? ?*
? ? ?* @param request request
? ? ?* @return String
? ? ?*/
? ? public String getBodyString(final ServletRequest request) {
? ? ? ? try {
? ? ? ? ? ? return inputStream2String(request.getInputStream());
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? log.error("", e);
? ? ? ? ? ? throw new RuntimeException(e);
? ? ? ? }
? ? }
?
? ? /**
? ? ?* 獲取請求Body
? ? ?*
? ? ?* @return String
? ? ?*/
? ? public String getBodyString() {
? ? ? ? final InputStream inputStream = new ByteArrayInputStream(body);?
? ? ? ? return inputStream2String(inputStream);
? ? }
?
? ? /**
? ? ?* 將inputStream里的數(shù)據(jù)讀取出來并轉(zhuǎn)換成字符串
? ? ?*
? ? ?* @param inputStream inputStream
? ? ?* @return String
? ? ?*/
? ? private String inputStream2String(InputStream inputStream) {
? ? ? ? StringBuilder sb = new StringBuilder();
? ? ? ? BufferedReader reader = null;
?
? ? ? ? try {
? ? ? ? ? ? reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset()));
? ? ? ? ? ? String line;
? ? ? ? ? ? while ((line = reader.readLine()) != null) {
? ? ? ? ? ? ? ? sb.append(line);
? ? ? ? ? ? }
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? log.error("", e);
? ? ? ? ? ? throw new RuntimeException(e);
? ? ? ? } finally {
? ? ? ? ? ? if (reader != null) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? reader.close();
? ? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ? log.error("", e);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
?
? ? ? ? return sb.toString();
? ? }
?
? ? @Override
? ? public BufferedReader getReader() throws IOException {
? ? ? ? return new BufferedReader(new InputStreamReader(getInputStream()));
? ? }
?
? ? @Override
? ? public ServletInputStream getInputStream() throws IOException {
?
? ? ? ? final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);?
? ? ? ? return new ServletInputStream() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public int read() throws IOException {
? ? ? ? ? ? ? ? return inputStream.read();
? ? ? ? ? ? }
?
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isFinished() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
?
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isReady() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
?
? ? ? ? ? ? @Override
? ? ? ? ? ? public void setReadListener(ReadListener readListener) {
? ? ? ? ? ? }
? ? ? ? };
? ? }?
}

定義一個過濾器 Filter

@Slf4j
public class ReplaceStreamFilter implements Filter {
?
? ? @Override
? ? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
? ? ? ? ServletRequest requestWrapper = new RequestWrapper((HttpServletRequest) request);
? ? ? ? chain.doFilter(requestWrapper, response);
? ? }
}

創(chuàng)建過濾器配置類 FilterConfig

@Configuration
public class FilterConfig {
?
? ? /**
? ? ?* 注冊過濾器
? ? ?*
? ? ?* @return FilterRegistrationBean
? ? ?*/
? ? @Bean
? ? public FilterRegistrationBean someFilterRegistration() {
? ? ? ? FilterRegistrationBean registration = new FilterRegistrationBean();
? ? ? ? registration.setFilter(replaceStreamFilter());
? ? ? ? registration.addUrlPatterns("/*");
? ? ? ? registration.setName("streamFilter");
? ? ? ? return registration;
? ? }
?
? ? /**
? ? ?* 實例化StreamFilter
? ? ?* @return Filter
? ? ?*/
? ? @Bean(name = "replaceStreamFilter")
? ? public Filter replaceStreamFilter() {
? ? ? ? return new ReplaceStreamFilter();
? ? }?
}

完成以上步驟即可在攔截器中讀取request中的body數(shù)據(jù) 

@Slf4j
@Component
public class APIInterceptor implements HandlerInterceptor {?
? ? /**
? ? ?* 預(yù)處理回調(diào)方法,實現(xiàn)處理器的預(yù)處理
? ? ?* 返回值:true表示繼續(xù)流程;false表示流程中斷,不會繼續(xù)調(diào)用其他的攔截器或處理器
? ? ?*/
? ? @Override
? ? public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
? ? ? ? log.info("開始攔截請求");
?
?? ??? ?if(isJson(request)){
?? ??? ??? ?String jsonParam = new RequestWrapper(request).getBodyString();
?? ??? ??? ?JSONObject params = JSONObject.parseObject(jsonParam);
?? ??? ??? ?......
?? ??? ??? ?return true;
?? ??? ?}?? ??? ?
?? ??? ?return false;
? ? }???
?
? ? /**
? ? ?* 返回json數(shù)據(jù)給前端
? ? ?* @param response
? ? ?* @param json
? ? ?*/
? ? protected void returnJson(ServletResponse response, JSONObject json){
? ? ? ? PrintWriter writer = null;
? ? ? ? response.setCharacterEncoding("UTF-8");
? ? ? ? response.setContentType("application/json; charset=utf-8");
? ? ? ? try {
? ? ? ? ? ? writer = response.getWriter();
? ? ? ? ? ? writer.print(json.toJSONString());
?
? ? ? ? } catch (IOException e) {
? ? ? ? ? ? log.error("response error",e);
? ? ? ? } finally {
? ? ? ? ? ? if (writer != null)
? ? ? ? ? ? ? ? writer.close();
? ? ? ? }
? ? }??
?
? ? /**
? ? ?* 判斷本次請求的數(shù)據(jù)類型是否為json
? ? ?* @param request request
? ? ?* @return boolean
? ? ?*/
? ? private boolean isJson(HttpServletRequest request) {
? ? ? ? if (request.getContentType() != null) {
? ? ? ? ? ? return request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE) ||
? ? ? ? ? ? ? ? ? ? request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE);
? ? ? ? }?
? ? ? ? return false;
? ? }

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java8中的 Lambda表達(dá)式教程

    Java8中的 Lambda表達(dá)式教程

    這篇文章主要介紹了 Java8中的 Lambda表達(dá)式教程,需要的朋友可以參考下
    2017-02-02
  • Java抽象類與接口區(qū)別詳解

    Java抽象類與接口區(qū)別詳解

    這篇文章主要介紹了Java抽象類與接口區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • SpringBoot?將配置文件掛到?jar?包外面的操作方法

    SpringBoot?將配置文件掛到?jar?包外面的操作方法

    在 SpringBoot 中,可以將配置文件放在 jar 包外面,這樣可以方便地修改配置而不需要重新打包和部署,這篇文章主要介紹了SpringBoot?如何將配置文件掛到?jar?包外面,需要的朋友可以參考下
    2023-03-03
  • JDK 14的新特性:文本塊Text Blocks的使用

    JDK 14的新特性:文本塊Text Blocks的使用

    這篇文章主要介紹了JDK 14的新特性:文本塊Text Blocks的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • spring boot @ResponseBody轉(zhuǎn)換JSON 時 Date 類型處理方法【兩種方法】

    spring boot @ResponseBody轉(zhuǎn)換JSON 時 Date 類型處理方法【兩種方法】

    這篇文章主要介紹了spring boot @ResponseBody轉(zhuǎn)換JSON 時 Date 類型處理方法,主要給大家介紹Jackson和FastJson兩種方式,每一種方法給大家介紹的都非常詳細(xì),需要的朋友可以參考下
    2018-08-08
  • 使用Spring?Boot如何限制在一分鐘內(nèi)某個IP只能訪問10次

    使用Spring?Boot如何限制在一分鐘內(nèi)某個IP只能訪問10次

    有些時候,為了防止我們上線的網(wǎng)站被攻擊,或者被刷取流量,我們會對某一個ip進(jìn)行限制處理,這篇文章,我們將通過Spring?Boot編寫一個小案例,來實現(xiàn)在一分鐘內(nèi)同一個IP只能訪問10次,感興趣的朋友一起看看吧
    2023-10-10
  • java服務(wù)端微信APP支付接口詳解

    java服務(wù)端微信APP支付接口詳解

    這篇文章主要為大家詳細(xì)介紹了java服務(wù)端微信APP支付接口,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Java單例模式實例簡述

    Java單例模式實例簡述

    這篇文章主要介紹了Java單例模式,在Java應(yīng)用程序設(shè)計中有著非常重要的作用,本文以實例形式對此加以簡單分析,需要的朋友可以參考下
    2014-09-09
  • springMVC使用ajaxFailUpload上傳圖片的方法

    springMVC使用ajaxFailUpload上傳圖片的方法

    這篇文章主要介紹了springMVC使用ajaxFailUpload上傳圖片的相關(guān)知識,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-06-06
  • Mybatis日志配置方式(slf4j、log4j、log4j2)

    Mybatis日志配置方式(slf4j、log4j、log4j2)

    這篇文章主要介紹了Mybatis日志配置方式(slf4j、log4j、log4j2),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評論