久久r热视频,国产午夜精品一区二区三区视频,亚洲精品自拍偷拍,欧美日韩精品二区

您的位置:首頁技術(shù)文章
文章詳情頁

SpringBoot攔截器如何獲取http請求參數(shù)

瀏覽:55日期:2023-04-27 08:17:29

1.1、獲取http請求參數(shù)是一種剛需

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

前置獲取參數(shù),統(tǒng)計請求數(shù)據(jù) 做服務(wù)的接口簽名校驗 敏感接口監(jiān)控日志 敏感接口防重復(fù)提交

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

1.2、定義攔截器獲取請求

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

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

/** * @author axin * @summary HTTP請求攔截器 */@Slf4jpublic class RequestInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //獲取請求參數(shù) String queryString = request.getQueryString(); log.info('請求參數(shù):{}', queryString); //獲取請求body byte[] bodyBytes = StreamUtils.copyToByteArray(request.getInputStream()); String body = new String(bodyBytes, request.getCharacterEncoding()); log.info('請求體:{}', body); return true; }}

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

/** * WebMVC配置,你可以集中在這里配置攔截器、過濾器、靜態(tài)資源緩存等 */@Configurationpublic class WebMvcConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new RequestInterceptor()).addPathPatterns('/**'); }}

定義個接口測試一下

/** * @author axin * @summary 提交測試接口 */@Slf4j@RestControllerpublic class MyHTTPController { @GetMapping('/v1/get') public void get(@RequestParam('one') String one, @RequestParam('two') BigDecimal number) { log.info('參數(shù):{},{}', one, number); } @PostMapping('/v1/post') public void check(@RequestBody User user) { log.info('{}', JSON.toJSONString(user)); }}

GET請求獲取請求參數(shù)示例:

SpringBoot攔截器如何獲取http請求參數(shù)

POST請求獲取請求Body示例:

SpringBoot攔截器如何獲取http請求參數(shù)

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

SpringBoot攔截器如何獲取http請求參數(shù)

1.3、為什么攔截器會重復(fù)調(diào)兩遍呢?

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

SpringBoot攔截器如何獲取http請求參數(shù)

1.4、ServletInputStream(CoyoteInputStream) 輸入流無法重復(fù)調(diào)用

而之前出現(xiàn)的 Required request body is missing 錯誤 其實是ServletInputStream被讀取后無法第二次再讀取了,所以我們要把讀取過的內(nèi)容存下來,然后需要的時候?qū)ν馓峁┛杀恢貜?fù)讀取的ByteArrayInputStream。

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

1.5、自定義 HttpServletRequestWrapper

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

/*** @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的外部組件,可以重點關(guān)注一下。 * @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 :

/*** @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); }}

然后配置一下:

/** * WebMVC配置,你可以集中在這里配置攔截器、過濾器、靜態(tài)資源緩存等 */@Configurationpublic 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(); }}

再調(diào)用一下 POST請求:

SpringBoot攔截器如何獲取http請求參數(shù)

請求成功!

1.5、總結(jié)一下 展望一下

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

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

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

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

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

到此這篇關(guān)于SpringBoot攔截器如何獲取http請求參數(shù)的文章就介紹到這了,更多相關(guān)SpringBoot攔截器獲取http請求參數(shù)內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 丹寨县| 江达县| 河源市| 利津县| 阿图什市| 长沙市| 大方县| 富源县| 东城区| 巨鹿县| 南充市| 长沙市| 宣武区| 昭平县| 古蔺县| 柳河县| 潞西市| 东乡县| 吴江市| 浪卡子县| 易门县| 郁南县| 武邑县| 绵竹市| 涿州市| 庄河市| 永川市| 阿图什市| 新民市| 建德市| 威远县| 乌鲁木齐县| 曲水县| 邢台市| 永清县| 福安市| 鄱阳县| 行唐县| 永年县| 深圳市| 江北区|