一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - SpringBoot攔截器如何獲取http請求參數

SpringBoot攔截器如何獲取http請求參數

2020-09-11 00:29上帝愛吃蘋果-Soochow Java教程

這篇文章主要給大家介紹了SpringBoot攔截器如何獲取http請求參數的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

1.1、獲取http請求參數是一種剛需

我想有的小伙伴肯定有過獲取http請求的需要,比如想

  1. 前置獲取參數,統計請求數據
  2. 做服務的接口簽名校驗
  3. 敏感接口監控日志
  4. 敏感接口防重復提交

等等各式各樣的場景,這時你就需要獲取 HTTP 請求的參數或者請求body,一般思路有兩種,一種就是自定義個AOP去攔截目標方法,第二種就是使用攔截器。整體比較來說,使用攔截器更靈活些,因為每個接口的請求參數定義不同,使用AOP很難細粒度的獲取到變量參數,本文主線是采用攔截器來獲取HTTP請求。

1.2、定義攔截器獲取請求

基于 spring-boot-starter-parent 2.1.9.RELEASE

看起來這個很簡單,這里就直接上code,定義個攔截器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * @author axin
 * @summary HTTP請求攔截器
 */
@Slf4j
public class RequestInterceptor implements HandlerInterceptor {
 
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 
    //獲取請求參數
    String queryString = request.getQueryString();
    log.info("請求參數:{}", queryString);
 
    //獲取請求body
    byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream());
    String body = new String(bodyBytes, request.getCharacterEncoding());
 
    log.info("請求體:{}", body);
    return true;
  }
}

然后把這個攔截器配置一下中:

?
1
2
3
4
5
6
7
8
9
10
11
/**
 * WebMVC配置,你可以集中在這里配置攔截器、過濾器、靜態資源緩存等
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
 
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");
  }
}

定義個接口測試一下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * @author axin
 * @summary 提交測試接口
 */
@Slf4j
@RestController
public class MyHTTPController {
 
  @GetMapping("/v1/get")
  public void get(@RequestParam("one") String one,
          @RequestParam("two") BigDecimal number) {
    log.info("參數:{},{}", one, number);
  }
 
 
  @PostMapping("/v1/post")
  public void check(@RequestBody User user) {
 
    log.info("{}", JSON.toJSONString(user));
  }
}

GET請求獲取請求參數示例:

SpringBoot攔截器如何獲取http請求參數

POST請求獲取請求Body示例:

SpringBoot攔截器如何獲取http請求參數

我們發現攔截器在獲取HTTP請求的body時出現了 400 (Required request body is missing: public void com.axin.world.controller.MyHTTPController.check(com.axin.world.domain.User));同時也發現攔截器竟然走了兩遍,這又是咋回事呢?

SpringBoot攔截器如何獲取http請求參數

1.3、為什么攔截器會重復調兩遍呢?

其實是因為 tomcat截取到異常后就轉發到/error頁面,就在這個轉發的過程中導致了springmvc重新開始DispatcherServlet的整個流程,所以攔截器執行了兩次,我們可以看下第二次調用時的url路徑:

SpringBoot攔截器如何獲取http請求參數

1.4、ServletInputStream(CoyoteInputStream) 輸入流無法重復調用

而之前出現的 Required request body is missing 錯誤 其實是ServletInputStream被讀取后無法第二次再讀取了,所以我們要把讀取過的內容存下來,然后需要的時候對外提供可被重復讀取的ByteArrayInputStream。

對于MVC的過濾器來說,我們就需要重寫 ServletInputStream 的 getInputStream()方法。

1.5、自定義 HttpServletRequestWrapper

為了 重寫 ServletInputStream 的 getInputStream()方法,我們需要自定義一個 HttpServletRequestWrapper :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/**
* @author Axin
* @summary 自定義 HttpServletRequestWrapper 來包裝輸入流
*/
public class AxinHttpServletRequestWrapper extends HttpServletRequestWrapper {
 
  /**
   * 緩存下來的HTTP body
   */
  private byte[] body;
 
  public AxinHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    body = StreamUtils.copyToByteArray(request.getInputStream());
  }
 
  /**
   * 重新包裝輸入流
   * @return
   * @throws IOException
   */
  @Override
  public ServletInputStream getInputStream() throws IOException {
    InputStream bodyStream = new ByteArrayInputStream(body);
    return new ServletInputStream() {
 
      @Override
      public int read() throws IOException {
        return bodyStream.read();
      }
 
      /**
       * 下面的方法一般情況下不會被使用,如果你引入了一些需要使用ServletInputStream的外部組件,可以重點關注一下。
       * @return
       */
      @Override
      public boolean isFinished() {
        return false;
      }
 
      @Override
      public boolean isReady() {
        return true;
      }
 
      @Override
      public void setReadListener(ReadListener readListener) {
 
      }
    };
  }
  
  @Override
  public BufferedReader getReader() throws IOException {
    InputStream bodyStream = new ByteArrayInputStream(body);
    return new BufferedReader(new InputStreamReader(getInputStream()));
  }
}

然后定義一個 DispatcherServlet子類來分派 上面自定義的 AxinHttpServletRequestWrapper :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author Axin
* @summary 自定義 DispatcherServlet 來分派 AxinHttpServletRequestWrapper
*/
public class AxinDispatcherServlet extends DispatcherServlet {
 
  /**
   * 包裝成我們自定義的request
   * @param request
   * @param response
   * @throws Exception
   */
  @Override
  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    super.doDispatch(new AxinHttpServletRequestWrapper(request), response);
  }
}

然后配置一下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * WebMVC配置,你可以集中在這里配置攔截器、過濾器、靜態資源緩存等
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
 
  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(new RequestInterceptor()).addPathPatterns("/**");
  }
 
  @Bean
  @Qualifier(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
  public DispatcherServlet dispatcherServlet() {
    return new AxinDispatcherServlet();
  }
}

再調用一下 POST請求:

SpringBoot攔截器如何獲取http請求參數

請求成功!

1.5、總結一下 展望一下

如果你想對HTTP請求做些騷操作,那么前置獲取HTTP請求參數是前提,為此文本給出了使用MVC攔截器獲取參數的樣例。

在獲取HTTP Body 的時候,出現了 Required request body is missing 的錯誤,同時攔截器還出現執行了兩遍的問題,這是因為 ServletInputStream被讀取了兩遍導致的,tomcat截取到異常后就轉發到 /error 頁面 被攔截器攔截到了,攔截器也就執行了兩遍。

為此我們通過自定義 HttpServletRequestWrapper 來包裝一個可被重讀讀取的輸入流,來達到期望的攔截效果。

在獲取到HTTP的請求參數后,我們可以前置做很多操作,比如常用的服務端接口簽名驗證,敏感接口防重復請求等等。

個人水平有限,如果文章有邏輯錯誤或表述問題還請指出,歡迎一起交流。

到此這篇關于SpringBoot攔截器如何獲取http請求參數的文章就介紹到這了,更多相關SpringBoot攔截器獲取http請求參數內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/keeya/p/13634015.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 69老司机亚洲精品一区 | 亚洲精品久久久久AV无码 | 美女张开腿让男人桶的 视频 | 日本xxxxxx片免费播放18 | 欧美va免费精品高清在线 | 合欢视频免费 | 三叶草私人研究所 | 日b视频免费| 男女精品视频 | 免费一级毛片在线播放放视频 | 国产日韩欧美在线一区二区三区 | 女人肮脏的交易中文字幕未删减版 | 91真人毛片一级在线播放 | 美女一级ba大片免色 | 亚洲啊v天堂 | 国产精品久久久久久久久免费 | 亚洲成人免费观看 | 非洲特级特黄aa大片 | 精品小视频在线观看 | 青青青青久久国产片免费精品 | 果冻传媒在线播放观看228集 | 丁香五香天堂网 | 美女把腿开让我 | 免费在线观看中文字幕 | 全弄乱纶小说 | 7777奇米四色 | 男人使劲躁女人视频免费 | 亚洲www美色 | 亚洲区精品久久一区二区三区 | 国产一区二区视频在线观看 | 白鹿扒开内裤露出尿孔 | 香蕉免费一区二区三区 | 日韩毛片免费 | 性白俄罗斯高清xxxxx | 热99在线观看 | 全日爱韩国视频在线观看 | 九九精品视频在线播放 | 国产精品一区二区久久 | 亚洲AV永久无码精品老司机蜜桃 | 日本在线小视频 | 亚洲精品动漫免费二区 |