Spring使用@Filter注解創(chuàng)建自定義過(guò)濾器
簡(jiǎn)介
Spring 框架提供了各種強(qiáng)大的功能來(lái)構(gòu)建健壯且可擴(kuò)展的應(yīng)用程序。 Spring 中鮮為人知但非常有用的注解之一是 @Filter,它支持自定義過(guò)濾器,可以將其應(yīng)用于 Spring 應(yīng)用程序以實(shí)現(xiàn)不同的目的,例如日志記錄、身份驗(yàn)證等。 在這篇文章中,我們將深入研究如何使用 Spring 的 @Filter 注解來(lái)創(chuàng)建自定義過(guò)濾器。
Spring Filters簡(jiǎn)介
過(guò)濾器在 Web 開(kāi)發(fā)中發(fā)揮著至關(guān)重要的作用,尤其是在基于 Spring 的 Web 應(yīng)用程序的上下文中。當(dāng)我們談?wù)?Spring 時(shí),我們主要集中在依賴注入、AOP(面向切面?編程)和 Data JPA 等功能上,而忽略了一些像Filter這樣的無(wú)名英雄。過(guò)濾器在許多方面都發(fā)揮了作用,例如安全、日志記錄、轉(zhuǎn)換以及各種其他類型的預(yù)處理和后處理活動(dòng)。
過(guò)濾器在 Web 應(yīng)用程序中的重要性
如果需要強(qiáng)制執(zhí)行訪問(wèn)控制(身份驗(yàn)證和授權(quán))、記錄傳入或輸出的 HTTP 請(qǐng)求和響應(yīng),或者在請(qǐng)求和響應(yīng)正文到達(dá)控制器或到達(dá)客戶端之前對(duì)其進(jìn)行操作,那么過(guò)濾器就發(fā)揮了作用。它們?yōu)闄M切關(guān)注點(diǎn)提供了一個(gè)集中處理,確保不必在應(yīng)用程序的多個(gè)部分中寫相同的邏輯,從而生成更干凈、更易于維護(hù)的代碼。
過(guò)濾器如何融入 Spring 生態(tài)系統(tǒng)
在 Spring 生態(tài)系統(tǒng)中,過(guò)濾器充當(dāng)著 Servlet 管道中的攔截器,這意味著它們有權(quán)在請(qǐng)求到達(dá)控制器之前(預(yù)處理)和響應(yīng)離開(kāi)控制器之后(后處理)執(zhí)行操作。 Spring 與 Java Servlet 規(guī)范很好地保持一致,因此,您可以在 Spring 應(yīng)用程序中使用本機(jī) Servlet 過(guò)濾器。然而,Spring 更進(jìn)一步,提供了一種使用注解及其強(qiáng)大的依賴注入功能來(lái)定義過(guò)濾器的優(yōu)雅方法。
@Filter 有什么作用
Spring 中的 @Filter 注釋(或用于類似目的的自定義注解)用于定義可以注冊(cè)并應(yīng)用于傳入請(qǐng)求的過(guò)濾器。它允許您將過(guò)濾邏輯與核心應(yīng)用程序邏輯完全分離,提供一種優(yōu)雅的方式將自定義操作添加到請(qǐng)求-響應(yīng)周期。使用@Filter,您可以簡(jiǎn)潔地表達(dá)特定的一段代碼旨在充當(dāng)過(guò)濾器,從而使代碼更易于理解和維護(hù)。
Servlet 過(guò)濾器與 Spring 過(guò)濾器
為什么要使用 Spring 特定的過(guò)濾器而不是標(biāo)準(zhǔn) Servlet 過(guò)濾器。雖然 Servlet 過(guò)濾器功能強(qiáng)大并且可以完成很多工作,但 Spring 過(guò)濾器受益于 Spring 的生態(tài)系統(tǒng),例如它的依賴注入功能,它允許您將 Spring 管理的 bean 直接連接到過(guò)濾器類中。這是傳統(tǒng) Servlet 過(guò)濾器無(wú)法做到的事情。
實(shí)踐
在本節(jié)中,我們將著眼于從頭開(kāi)始設(shè)置 Spring Boot 項(xiàng)目,重點(diǎn)關(guān)注包含必要的依賴項(xiàng)和配置以支持過(guò)濾器的使用。我們將討論兩種設(shè)置項(xiàng)目的方法:使用 Spring Initializr 和手動(dòng)設(shè)置。
剖析過(guò)濾器
了解過(guò)濾器的結(jié)構(gòu)對(duì)于充分利用其功能至關(guān)重要?;?Spring 的應(yīng)用程序中的過(guò)濾器可以與 Java 的本機(jī) Servlet Filter 保持一致,也可以使用 Spring 的特定功能來(lái)實(shí)現(xiàn)更加自定義的方法。要掌握過(guò)濾器的本質(zhì),就必須探索其核心方法——過(guò)濾器鏈,以及如何正確配置過(guò)濾器。
過(guò)濾器中的核心方法
Spring(或一般的 Java Web 應(yīng)用程序)中的典型過(guò)濾器本質(zhì)上是一個(gè) Java 類,它實(shí)現(xiàn)了 javax.servlet 包中的 Filter 接口。該接口定義了三個(gè)方法:
init(FilterConfig filterConfig)
該方法在過(guò)濾器的生命周期內(nèi)僅被調(diào)用一次。您可以在此處放置初始化邏輯,例如分配資源。 FilterConfig 對(duì)象提供對(duì)過(guò)濾器配置參數(shù)的訪問(wèn),您可以使用此對(duì)象來(lái)獲取 Spring 配置中定義的初始化參數(shù)。
doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
這是過(guò)濾器的主要邏輯,每次請(qǐng)求響應(yīng)都會(huì)調(diào)用這個(gè)方法。ServletRequest和ServletResponse分別表示輸入請(qǐng)求和輸出回復(fù),在此方法中調(diào)用chain.doFilter會(huì)將請(qǐng)求和響應(yīng)傳給過(guò)濾器鏈中的下一個(gè)實(shí)體(過(guò)濾器鏈或者目標(biāo)資源例如控制器)
destory()
當(dāng)過(guò)濾器停止服務(wù)或者程序關(guān)閉時(shí)調(diào)用。通常做的是一些清理資源的工作,例如關(guān)閉數(shù)據(jù)庫(kù)連接、關(guān)閉文件等。
理解FilterChain(過(guò)濾器鏈)
過(guò)濾器鏈表示是請(qǐng)求和響應(yīng)經(jīng)過(guò)的一系列的的過(guò)濾器,就和一根鏈條一樣。過(guò)濾器添加到鏈中的順序很重要,如果Filter A修改了請(qǐng)求對(duì)象,那么鏈中的下一個(gè)Filter B將接收修改后的請(qǐng)求。
如何在Spring中配置Filter
雖然可以使用@Component注解配置Filter class使得sping可以自動(dòng)檢測(cè)并應(yīng)用,但這會(huì)造成過(guò)濾器應(yīng)用到每個(gè)請(qǐng)求。為了進(jìn)行更精細(xì)的控制,可以使用 FilterRegistrationBean,這個(gè)類可以配置過(guò)濾器應(yīng)用到哪個(gè)Url或者Servlet。
下面是示例
@Bean public FilterRegistrationBean<CustomFilter> loggingFilter() { FilterRegistrationBean<CustomFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new CustomFilter()); registrationBean.addUrlPatterns("/api/*"); return registrationBean; }
這個(gè)例子中,我們的過(guò)濾器只對(duì)以api開(kāi)頭的請(qǐng)求有效。
一個(gè)簡(jiǎn)單的日志過(guò)濾器
為了將所有這些概念聯(lián)系在一起,讓我們回顧一下簡(jiǎn)單的日志過(guò)濾器示例:
import javax.servlet.*; import java.io.IOException; public class LoggingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { // 初始化 System.out.println("Logging Filter initialized"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("Request received at " + new java.util.Date()); chain.doFilter(request, response); System.out.println("Response sent at " + new java.util.Date()); } @Override public void destroy() { // 清理資源 System.out.println("Logging Filter destroyed"); } }
在這個(gè)例子中,實(shí)現(xiàn)了三個(gè)主要的方法,init()輸出了一些初始化方法,doFilter記錄了請(qǐng)求進(jìn)來(lái)的時(shí)間和響應(yīng)回復(fù)的時(shí)間,destory()記錄了資源清理的時(shí)間。
使用@Filter創(chuàng)建自定義過(guò)濾器
使用@Filter注解創(chuàng)建自定義過(guò)濾器給程序添加特定的功能是非常有效的,這種自定義過(guò)濾器以聲明的方式在特定方法或者路由上應(yīng)用過(guò)濾器,是代碼更加簡(jiǎn)介且容易維護(hù)。
創(chuàng)建@Filter注解
第一步是創(chuàng)建 @Filter 注解本身。這將是一個(gè)標(biāo)記注解,用于標(biāo)識(shí)哪些控制器或方法應(yīng)受到過(guò)濾器的影響
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface Filter { String value() default ""; }
創(chuàng)建一個(gè)@Filter過(guò)濾器類
現(xiàn)在,讓我們創(chuàng)建一個(gè)將執(zhí)行實(shí)際邏輯的自定義過(guò)濾器類。要使用 @Filter 注釋,自定義過(guò)濾器類應(yīng)檢查其是否存在。
import org.springframework.core.annotation.AnnotationUtils; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import java.io.IOException; public class CustomFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; String path = httpRequest.getRequestURI(); Class<?> controller = if (controller != null && AnnotationUtils.findAnnotation(controller, Filter.class) != null) { System.out.println("Custom filter applied"); } chain.doFilter(request, response); } }
注冊(cè)自定義過(guò)濾器
為了讓自定義過(guò)濾器正常工作,我們需要注冊(cè)它。您可以使用 Spring 的 FilterRegistrationBean 以編程方式實(shí)現(xiàn)。
import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FilterConfig { @Bean public FilterRegistrationBean<CustomFilter> customFilterRegistration() { FilterRegistrationBean<CustomFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new CustomFilter()); registrationBean.addUrlPatterns("/*"); // Apply to all routes return registrationBean; } }
通過(guò)此配置,自定義過(guò)濾器將應(yīng)用于所有路由。您可以更改 addUrlPatterns 方法參數(shù)來(lái)限制應(yīng)應(yīng)用過(guò)濾器的路由。
使用自定義過(guò)濾器注解
現(xiàn)在自定義過(guò)濾器和 @Filter 注解已準(zhǔn)備就緒,現(xiàn)在可以注解控制器或特定方法。
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController @Filter("Some Value") public class MyController { @GetMapping("/hello") public String hello() { return "Hello, World!"; } }
使用場(chǎng)景和最佳實(shí)踐
過(guò)濾器為 Spring Boot 應(yīng)用程序提供了強(qiáng)大的自定義功能,并且可以通過(guò)多種方式利用它們來(lái)滿足不同的需求。下面,我們將介紹一些使用過(guò)濾器的常見(jiàn)用例,并研究實(shí)施過(guò)濾器時(shí)要遵循的最佳實(shí)踐。
使用場(chǎng)景
認(rèn)證與授權(quán):過(guò)濾器是在允許請(qǐng)求繼續(xù)發(fā)送到控制器之前執(zhí)行身份驗(yàn)證和授權(quán)檢查的理想工具。這可確保只有授權(quán)用戶才能訪問(wèn)應(yīng)用程序的特定部分。
記錄和監(jiān)控:過(guò)濾器可以記錄有關(guān)請(qǐng)求和響應(yīng)的基本信息,例如 IP 地址、標(biāo)頭、有效負(fù)載大小和執(zhí)行時(shí)間。這些信息有利于調(diào)試和監(jiān)控。
數(shù)據(jù)轉(zhuǎn)換: 可以使用過(guò)濾器來(lái)轉(zhuǎn)換請(qǐng)求和響應(yīng)數(shù)據(jù),例如,通過(guò)添加默認(rèn)參數(shù)、執(zhí)行數(shù)據(jù)轉(zhuǎn)換或使用附加信息豐富響應(yīng)。
速率限制:過(guò)濾器可以通過(guò)計(jì)算給定時(shí)間范圍內(nèi)來(lái)自特定客戶端的請(qǐng)求數(shù)量來(lái)幫助限制速率,然后根據(jù)這些計(jì)數(shù)阻止或允許請(qǐng)求。
最佳實(shí)踐
把事情簡(jiǎn)單化:過(guò)濾器不適合復(fù)雜業(yè)務(wù)邏輯。它們應(yīng)該盡可能輕量級(jí),以確保它們不會(huì)成為性能瓶頸。
注意過(guò)濾器鏈: 永遠(yuǎn)記住調(diào)用 chain.doFilter(request, response) 來(lái)繼續(xù)執(zhí)行過(guò)濾器鏈。否則,請(qǐng)求將被阻止,并且無(wú)法到達(dá)預(yù)期的效果。
執(zhí)行順序: 過(guò)濾器注冊(cè)和執(zhí)行的順序很重要。如果處理依賴于先前的過(guò)濾器,請(qǐng)確保設(shè)置順序。
徹底測(cè)試 : 過(guò)濾器與每個(gè)傳入請(qǐng)求和傳出響應(yīng)交互。因此,嚴(yán)格的測(cè)試對(duì)于確保它們?cè)诟鞣N條件下表現(xiàn)出預(yù)期的效果至關(guān)重要。
利用 Spring 的靈活性: Spring Boot 允許通過(guò)多種方式來(lái)注冊(cè)和應(yīng)用過(guò)濾器。利用這種靈活性來(lái)創(chuàng)建模塊化且可維護(hù)的代碼。
總結(jié)
在這篇文章中,我們了解了在 Spring 應(yīng)用程序中使用過(guò)濾器的要點(diǎn)和復(fù)雜性。從了解過(guò)濾器的結(jié)構(gòu)到設(shè)置 Spring Boot 項(xiàng)目,再到使用專門的 @Filter 注釋創(chuàng)建自定義過(guò)濾器,我們涵蓋了很多信息。我們還深入研究了過(guò)濾器非常有用的現(xiàn)實(shí)用例,以及實(shí)施過(guò)濾器時(shí)要遵循的最佳實(shí)踐。
當(dāng)您開(kāi)發(fā)和維護(hù) Spring Boot 應(yīng)用程序時(shí),過(guò)濾器提供了一種強(qiáng)大的模塊化方法來(lái)處理各種橫切問(wèn)題,例如日志記錄、身份驗(yàn)證和數(shù)據(jù)轉(zhuǎn)換等。了解如何正確實(shí)現(xiàn)和使用過(guò)濾器可以極大地增強(qiáng)應(yīng)用程序的功能、安全性和整體質(zhì)量。
以上就是Spring使用@Filter注解創(chuàng)建自定義過(guò)濾器的詳細(xì)內(nèi)容,更多關(guān)于Spring Filter自定義過(guò)濾器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot配置logback日志管理過(guò)程詳解
這篇文章主要介紹了springboot配置logback日志管理過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09SpringBoot事件發(fā)布與監(jiān)聽(tīng)超詳細(xì)講解
今天去官網(wǎng)查看spring boot資料時(shí),在特性中看見(jiàn)了系統(tǒng)的事件及監(jiān)聽(tīng)章節(jié),所以下面這篇文章主要給大家介紹了關(guān)于SpringBoot事件發(fā)布和監(jiān)聽(tīng)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-11-11Elasticsearch8.1中的Script使用實(shí)例深入解讀
這篇文章主要為大家介紹了Elasticsearch8.1中的Script使用實(shí)例深入解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10Maven倉(cāng)庫(kù)鏡像配置的方法實(shí)現(xiàn)
本文介紹了如何使用Maven倉(cāng)庫(kù)鏡像來(lái)加速構(gòu)建過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12springboot接口返回?cái)?shù)據(jù)類型全面解析
這篇文章主要介紹了springboot接口返回?cái)?shù)據(jù)類型問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12java中@DateTimeFormat和@JsonFormat注解的使用
本文主要介紹了java中@DateTimeFormat和@JsonFormat注解的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-08-08Java數(shù)組轉(zhuǎn)換為L(zhǎng)ist的四種方式
這篇文章主要介紹了Java開(kāi)發(fā)技巧數(shù)組轉(zhuǎn)List的四種方式總結(jié),每種方式結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-09-09