Java的Servlet、Filter、Interceptor、Listener

寫在前面:

使用Spring-Boot時,嵌入式Servlet容器可以通過掃描注解(@ServletComponentScan)的方式注冊Servlet、Filter和Servlet規范的所有監聽器(如HttpSessionListener監聽器)。?

Spring boot 的主 Servlet 為 DispatcherServlet,其默認的url-pattern為“/”。一般情況系統默認的Servlet就夠用了,如果需要自定義Servlet,可以繼承系統抽象類HttpServlet,重寫方法來實現自己的Servlet。關于Servlet、過濾器、攔截器、監聽器可以參考:(轉)servlet、filter、listener、interceptor之間的區別和聯系

Spring-Boot有兩種方法注冊Servlet、Filter和Listener?:

1、代碼注冊:通過ServletRegistrationBean、 FilterRegistrationBean 和 ServletListenerRegistrationBean 獲得控制。

2、在 SpringBootApplication 上使用@ServletComponentScan 注解后,Servlet、Filter、Listener 可以直接通過 @WebServlet、@WebFilter、@WebListener 注解自動注冊,無需其他代碼。

一、Servlet

Servlet匹配規則:匹配的優先級是從精確到模糊,復合條件的Servlet并不會都執行。

1、通過@ServletComponentScan自動掃描

a、springboot的啟動入口添加注解:@ServletComponentScan;

?

@SpringBootApplication
@ServletComponentScan
public class ApplicationMain {public static void main(String[] args) {SpringApplication.run(ApplicationMain.class, args);}
}

?

b、@WebServlet 自定義Servlet,配置處理請求路徑?/demo/myServlet?

@WebServlet(name = "myServletDemo1",urlPatterns = "/demo/myServlet",description = "自定義的servlet")
public class MyServletDemo1 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo Get Method==========");resp.getWriter().println("my myServletDemo1 process request");super.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo1 POST Method==========");super.doPost(req, resp);}
}

?

2、使用@ServletRegistrationBean注解

a、@ServletRegistrationBean注入自定義的Servlet,配置處理的路徑為?/demo/servletDemo2?

@Configuration
public class ServletConfiguration {/*** 代碼注入*/@Beanpublic ServletRegistrationBean myServletDemo() {return new ServletRegistrationBean(new MyServletDemo2(), "/demo/servletDemo2");}
}

b、自定義的Servlet

public class MyServletDemo2 extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo2 Get Method==========");resp.getWriter().println("my myServletDemo2 process request");super.doGet(req, resp);}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("==========myServletDemo2 POST Method==========");super.doPost(req, resp);}
}

?

二、Filter

完整的流程是:Filter對用戶請求進行預處理,接著將請求交給Servlet進行處理并生成響應,最后Filter再對服務器響應進行后處理。

Filter有如下幾個用處。

  • 在HttpServletRequest到達Servlet之前,攔截客戶的HttpServletRequest。
  • 根據需要檢查HttpServletRequest,也可以修改HttpServletRequest頭和數據。
  • 在HttpServletResponse到達客戶端之前,攔截HttpServletResponse。
  • 根據需要檢查HttpServletResponse,也可以修改HttpServletResponse頭和數據。

多個FIlter可以組成過濾器調用鏈,按設置的順序逐一進行處理,形成Filter調用鏈。

1、通過@ServletComponentScan自動掃描

a、springboot的啟動入口添加注解:@ServletComponentScan;

b、@WebFilter 配置處理全部url的Filter

@WebFilter(filterName = "myFilter",urlPatterns = "/*")
public class MyFilter implements Filter {public void init(FilterConfig filterConfig) throws ServletException {System.out.println(">>>>>>myFilter init ……");}public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println(">>>>>>執行過濾操作");filterChain.doFilter(servletRequest, servletResponse);}public void destroy() {System.out.println(">>>>>>myFilter destroy ……");}
}

?*?doFilter()方法是過濾器的核心方法,實現該方法就可實現對用戶請求進行預處理,也可實現對服務器響應進行后處理——它們的分界線為是否調用了filterChain.doFilter(),執行該方法之前,即對用戶請求進行預處理;執行該方法之后,即對服務器響應進行后處理。

2、通過@FilterRegistrationBean注冊

a、@Bean注入自定義的Filter

@Configuration
public class ServletConfiguration {@Beanpublic FilterRegistrationBean myFilterDemo(){FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter2());registration.addUrlPatterns("/demo/myFilter2");registration.addInitParameter("paramName", "paramValue");registration.setName("myFilter2");registration.setOrder(2);//指定filter的順序return registration;}
}

b、自定義的Filter

public class MyFilter2 implements Filter {public void init(FilterConfig filterConfig) throws ServletException {System.out.println("======MyFilter2 init ……");}public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {System.out.println("======MyFilter2執行過濾操作");filterChain.doFilter(servletRequest, servletResponse);}public void destroy() {System.out.println("======MyFilter2 destroy ……");}
}

三、Listener

目前 Servlet 中提供了 6 種兩類事件的觀察者接口,它們分別是:4 個 EventListeners 類型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 個 LifecycleListeners 類型的,ServletContextListener、HttpSessionListener。

  • ServletContextAttributeListener監聽對ServletContext屬性的操作,比如增加、刪除、修改屬性。
  • ServletContextListener監聽ServletContext。當創建ServletContext時,激發contextInitialized(ServletContextEvent sce)方法;當銷毀ServletContext時,激發contextDestroyed(ServletContextEvent sce)方法。
  • HttpSessionListener監聽HttpSession的操作。當創建一個Session時,激發session Created(HttpSessionEvent se)方法;當銷毀一個Session時,激發sessionDestroyed (HttpSessionEvent se)方法。
  • HttpSessionAttributeListener監聽HttpSession中的屬性的操作。當在Session增加一個屬性時,激發attributeAdded(HttpSessionBindingEvent se) 方法;當在Session刪除一個屬性時,激發attributeRemoved(HttpSessionBindingEvent se)方法;當在Session屬性被重新設置時,激發attributeReplaced(HttpSessionBindingEvent se) 方法。

1、通過@ServletComponentScan自動掃描

a、ServletListenerRegistrationBean?注入自定義的Listener;

b、自定義的Listener

@WebListener
public class MyLisener implements ServletContextListener {public void contextInitialized(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextInitialized method");}public void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextDestroyed method");}
}

2、通過@ServletListenerRegistrationBean?注冊

a、@Bean注入自定義的Listener;

@Configuration
public class ServletConfiguration {@Beanpublic ServletListenerRegistrationBean myListener(){return new ServletListenerRegistrationBean(new MyLisener());}
}

b、自定義的Listener

public class MyLisener implements ServletContextListener {public void contextInitialized(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextInitialized method");}public void contextDestroyed(ServletContextEvent servletContextEvent) {System.out.println("MyLisener contextDestroyed method");}
}?

四、驗證servlet、filter、listener的順序

a、使用MyServletDemo2、MyFilter2、MyFilter3、MyLisener做測試;

b、設置servlet處理url格式為?/demo/*;設置MyFilter2順序為2;MyFilter3的順序為3;

@Configuration
public class ServletConfiguration {/**代碼注入*/@Beanpublic ServletRegistrationBean myServletDemo(){return new ServletRegistrationBean(new MyServletDemo2(),"/demo/*");}@Beanpublic FilterRegistrationBean myFilterDemo(){FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter2());registration.addUrlPatterns("/demo/myFilter");registration.addInitParameter("paramName", "paramValue");registration.setName("myFilter2");registration.setOrder(2);//指定filter的順序return registration;}@Beanpublic FilterRegistrationBean myFilterDemo2(){FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(new MyFilter3());registration.addUrlPatterns("/demo/*");registration.addInitParameter("paramName", "paramValue");registration.setName("myFilter3");registration.setOrder(1);return registration;}@Beanpublic ServletListenerRegistrationBean myListener(){return new ServletListenerRegistrationBean(new MyLisener());}
}
View Code

c、啟動項目后輸出:(FIlter2先執行init,因為@Ben在前)

MyLisener contextInitialized method
======MyFilter2 init ……
======MyFilter3 init ……

d、瀏覽器輸入地址地址:http://localhost:8080/demo/myFilter,輸出:

======MyFilter3執行過濾操作
======MyFilter2執行過濾操作
>>>>>>>>>>test Get Method==========

可以看出:

  1. Filter3比Filter2先執行;
  2. Filter可以匹配上的url都會執行,并且按順序執行(Filter的調用鏈);
  3. Filter比servlet先執行。
  4. servlet先按具體匹配,然后模糊匹配,并且只能有一個servlet匹配上,沒有servlet調用鏈。

執行順序是:Listener》Filter》Servlet

五、ApplicationListener自定義偵聽器類

參考:http://blog.csdn.net/liaokailin/article/details/48186331

六、Interceptor

攔截器只會處理DispatcherServlet處理的url

a、自定義攔截器

public class MyInterceptor implements HandlerInterceptor {public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {System.out.println(">>>>MyInterceptor preHandle");return true;}public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {System.out.println(">>>>MyInterceptor postHandle");}public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {System.out.println(">>>>MyInterceptor afterCompletion");}
}

?

b、注冊攔截器

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");super.addInterceptors(registry);}
}

c、攔截器驗證

輸入地址:http://localhost:8080/home/test

>>>>MyInterceptor preHandle
>>>>MyInterceptor postHandle
>>>>MyInterceptor afterCompletion

輸入地址:http://localhost:8080/demo/myFilter (自定義的Servlet處理了請求,此時攔截器不處理)

攔截器不處理。

轉載于:https://www.cnblogs.com/mr-yang-localhost/p/7784607.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390854.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390854.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390854.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

html5教程_最好HTML和HTML5教程

html5教程HyperText Markup Language (HTML) is a markup language used to construct online documents and is the foundation of most websites today. A markup language like HTML allows us to超文本標記語言(HTML)是用于構造在線文檔的標記語言,并且是當今大…

leetcode 1035. 不相交的線(dp)

在兩條獨立的水平線上按給定的順序寫下 nums1 和 nums2 中的整數。 現在,可以繪制一些連接兩個數字 nums1[i] 和 nums2[j] 的直線,這些直線需要同時滿足滿足: nums1[i] nums2[j] 且繪制的直線不與任何其他連線(非水平線&#x…

SPI和RAM IP核

學習目的: (1) 熟悉SPI接口和它的讀寫時序; (2) 復習Verilog仿真語句中的$readmemb命令和$display命令; (3) 掌握SPI接口寫時序操作的硬件語言描述流程(本例僅…

個人技術博客Alpha----Android Studio UI學習

項目聯系 這次的項目我在前端組,負責UI,下面簡略講下學到的內容和使用AS過程中遇到的一些問題及其解決方法。 常見UI控件的使用 1.TextView 在TextView中,首先用android:id給當前控件定義一個唯一標識符。在活動中通過這個標識符對控件進行事…

數據科學家數據分析師_站出來! 分析人員,數據科學家和其他所有人的領導和溝通技巧...

數據科學家數據分析師這一切如何發生? (How did this All Happen?) As I reflect on my life over the past few years, even though I worked my butt off to get into Data Science as a Product Analyst, I sometimes still find myself begging the question, …

leetcode 810. 黑板異或游戲

黑板上寫著一個非負整數數組 nums[i] 。Alice 和 Bob 輪流從黑板上擦掉一個數字,Alice 先手。如果擦除一個數字后,剩余的所有數字按位異或運算得出的結果等于 0 的話,當前玩家游戲失敗。 (另外,如果只剩一個數字,按位異…

react-hooks_在5分鐘內學習React Hooks-初學者教程

react-hooksSometimes 5 minutes is all youve got. So in this article, were just going to touch on two of the most used hooks in React: useState and useEffect. 有時只有5分鐘。 因此,在本文中,我們僅涉及React中兩個最常用的鉤子: …

分析工作試用期收獲_免費使用零編碼技能探索數據分析

分析工作試用期收獲Have you been hearing the new industry buzzword — Data Analytics(it was AI-ML earlier) a lot lately? Does it sound complicated and yet simple enough? Understand the logic behind models but dont know how to code? Apprehensive of spendi…

select的一些問題。

這個要怎么統計類別數呢? 哇哇哇 解決了。 之前怎么沒想到呢?感謝一樓。轉載于:https://www.cnblogs.com/AbsolutelyPerfect/p/7818701.html

html5語義化標記元素_語義HTML5元素介紹

html5語義化標記元素Semantic HTML elements are those that clearly describe their meaning in a human- and machine-readable way. 語義HTML元素是以人類和機器可讀的方式清楚地描述其含義的元素。 Elements such as <header>, <footer> and <article> …

重學TCP協議(12)SO_REUSEADDR、SO_REUSEPORT、SO_LINGER

1. SO_REUSEADDR 假如服務端出現故障&#xff0c;主動斷開連接以后&#xff0c;需要等 2 個 MSL 以后才最終釋放這個連接&#xff0c;而服務重啟以后要綁定同一個端口&#xff0c;默認情況下&#xff0c;操作系統的實現都會阻止新的監聽套接字綁定到這個端口上。啟用 SO_REUSE…

殘疾科學家_數據科學與殘疾:通過創新加強護理

殘疾科學家Could the time it takes for you to water your houseplants say something about your health? Or might the amount you’re moving around your neighborhood reflect your mental health status?您給植物澆水所需的時間能否說明您的健康狀況&#xff1f; 還是…

POJ 3660 Cow Contest [Floyd]

POJ - 3660 Cow Contest http://poj.org/problem?id3660 N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code better than others. Each cow has a certain constant skill rating that is un…

Linux 網絡相關命令

1. telnet 1.1 檢查端口是否打開 執行 telnet www.baidu.com 80&#xff0c;粘貼下面的文本&#xff08;注意總共有四行&#xff0c;最后兩行為兩個空行&#xff09; telnet [domainname or ip] [port]例如&#xff1a; telnet www.baidu.com 80 如果這個網絡連接可達&…

JSON.parseObject(String str)與JSONObject.parseObject(String str)的區別

一、首先來說說fastjson fastjson 是一個性能很好的 Java 語言實現的 JSON 解析器和生成器&#xff0c;來自阿里巴巴的工程師開發。其主要特點是&#xff1a; ① 快速&#xff1a;fastjson采用獨創的算法&#xff0c;將parse的速度提升到極致&#xff0c;超過所有基于Java的jso…

jQuery Ajax POST方法

Sends an asynchronous http POST request to load data from the server. Its general form is:發送異步http POST請求以從服務器加載數據。 其一般形式為&#xff1a; jQuery.post( url [, data ] [, success ] [, dataType ] )url : is the only mandatory parameter. This…

spss23出現數據消失_改善23億人口健康數據的可視化

spss23出現數據消失District Health Information Software, or DHIS2, is one of the most important sources of health data in low- and middle-income countries (LMICs). Used by 72 different LMIC governments, DHIS2 is a web-based open-source platform that is used…

01-hibernate注解:類級別注解,@Entity,@Table,@Embeddable

Entity Entity:映射實體類 Entity(name"tableName") name:可選&#xff0c;對應數據庫中一個表&#xff0c;若表名與實體類名相同&#xff0c;則可以省略。 注意&#xff1a;使用Entity時候必須指定實體類的主鍵屬性。 第一步&#xff1a;建立實體類&#xff1a; 分別…

leetcode 1707. 與數組中元素的最大異或值

題目 給你一個由非負整數組成的數組 nums 。另有一個查詢數組 queries &#xff0c;其中 queries[i] [xi, mi] 。 第 i 個查詢的答案是 xi 和任何 nums 數組中不超過 mi 的元素按位異或&#xff08;XOR&#xff09;得到的最大值。換句話說&#xff0c;答案是 max(nums[j] XO…

MySQL基礎入門學習【2】數據類型

數據類型&#xff1a;指列、存儲過程參數、表達式和局部變量的數據特征&#xff0c;它決定了數據的存儲格式&#xff0c;代表了不同的信息類型 &#xff08;1&#xff09; 整型(按存儲范圍分類)&#xff1a;TINYINT&#xff08;1字節&#xff09; SAMLLINT&#xff08;2字節&am…