前幾天寫了關于DispatcherServlet如何執行個體化的,今天我們來看一下java web的三大元件:Servlet、Filter、Listener。
不知道小夥伴們對這三個元件是否熟悉呢?感覺自從用了Spring架構後,很多元件都幫我們封裝好了,感覺這三個裡面,Filter是最常用的,至少我用過幾次[淚奔]
Listener簡介
Listener表示伺服器的事件監聽器,用于監聽三個域對象的狀态(對象、對象的屬性)變化,三個域對象分别是ServletContext、HttpSession、HttpServletRequest
Spring中可以使用ServletListenerRegistrationBean注冊器進行注冊監聽
對于三大域對象,大家是否熟悉呢?改天寫一篇關于三大域對象的文章
- ServletContext
ServletContextListener:ServletContextListener負責監聽 ServletContext 的建立和銷毀,就可以監聽伺服器的啟動和關閉。這樣我們就可以在伺服器啟動和關閉的時候執行一些任務,比如伺服器啟動之後讀取Spring Framework 的配置檔案(applicationContext.xml),建立Spring的核心容器,我們的ContextLoaderListener就是實作了ServletContextListener,由AbstractContextLoaderInitializer進行注冊,并初始化Spring的IOC容器的。
ServletContextAttributeListener:監聽全局作用域對象共享資料變化時刻。當我向ServletContext域對象中添加修改删除值時,都可以通過監聽擷取到對應的動作。
- HttpSession
HttpSessionListener:當一個浏覽器第一次通路網站的時候,J2EE應用伺服器會建立一個HttpSession對象 ,并觸發 HttpSession建立事件 ,如果注冊了HttpSessionListener事件監聽器,則會調用HttpSessionListener事件監聽器的 sessionCreated方法。相反,當這個浏覽器通路結束逾時的時候,J2EE應用伺服器會銷毀相應的HttpSession對象,觸發 HttpSession銷毀事件,同時調用所注冊HttpSessionListener事件監聽器的sessionDestroyed方法
HttpSessionActivationListener:實作了HttpSessionActivationListener接口的 JavaBean 對象可以感覺自己被活化和鈍化的事件。當綁定到 HttpSession 對象中的對象将要随 HttpSession 對象被鈍化之前,web 伺服器調用如下方法sessionWillPassivate(HttpSessionBindingEvent event) 方法;當綁定到 HttpSession 對象中的對象将要随 HttpSession 對象被活化之後,web 伺服器調用該對象的 void sessionDidActive(HttpSessionBindingEvent event)方法。所謂的鈍化狀态,就是将Session記憶體中的對象持久化(序列化)到磁盤;活化狀态,就是将磁盤上的對象再次恢複到session記憶體中。
HttpSessionBindingListener:實作BindingListener接口的對象被綁定到session時觸發valueBound事件即setAttribute時,解除綁定即session銷毀時觸發valueUnbound事件。我們綁定到指定session中:session.setAttribute("名字",BindingListener接口實作對象);
HttpSessionAttributeListener:這個與ServletContextAttributeListener一樣功能,監聽的是HttpSession域對象中的内容
- HttpServletRequest
ServletRequestListener:這個接口是在每次請求的時候就會執行監聽,HttpServletRequest可以直接注入就是使用了ServletRequestListener接口監聽了每次請求對象,相關文章:RequestObjectFactory()是怎麼捕捉到每次請求的HTTP對象的
ServletRequestAttributeListener:這個與ServletContextAttributeListener一樣的功能,隻是監聽的是HttpServletRequest域對象中的内容
Filter簡介
當通路伺服器的資源時,過濾器可以将請求攔截下來,完成一些特殊功能,例如:登入驗證、統一編碼處理、敏感字元過濾……
鄙人曾經使用Filter進行了ServletRequest包裝處理,進而可以使ServletRequest可以多次讀取,因為ServletRequest的getInputStream方法隻能使用一次,但是我還想在到達Controller之前用攔截器對請求内容進行一次處理,是以我使用過濾器将ServletRequest包裝一下。
@WebFilter(urlPatterns = "/*")
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestWrapperFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//将ServletRequest封裝一下,因為request.getInputStream()方法隻能讀取一次,是以不能和@requestBody一起使用
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
log.info("WebRqsTypeChangeFilter----->"+new String(requestWrapper.getBody()));
chain.doFilter(requestWrapper, response);
}
}
//也可以使用下面這種方式進行注冊過濾器,也可以直接使用@WebFilter注解
@Bean
public FilterRegistrationBean<GenericFilterBean> jwtFilter() throws NoSuchAlgorithmException {
FilterRegistrationBean<GenericFilterBean> registration = new FilterRegistrationBean<>();
registration.setFilter(new RequestWrapperFilter());
registration.addUrlPatterns("/api/*");
registration.setOrder(2);
return registration;
}
Servlet簡介
Servlet(Server Applet)伺服器的小程式。是用java編寫的一個伺服器程式,目的是和浏覽器互動并且生成動态的web内容。Servlet狹義上來講指的是servlet接口,廣義上來講指的是所有實作接口的實作類。
Servlet是指實作了Servlet接口類,Servlet運作于支援java的應用伺服器(tomcat,Servlet是tomcat的一個元件)中。從原理上來講,Servlet可以響應任何類型的請求,但絕大多數情況下Servlet隻用來擴充基于HTTP協定的Web服務
Servlet生命周期:從建立到銷毀的全過程,共分為三個階段
- 初始化init方法: 隻會執行一次(啟動tomcat的時候預設是不執行的,在通路的時候才會執行)
- 服務方法service: 可以執行多次,每次請求會執行
- 銷毀方法destory: 隻執行一次(停止伺服器)
//簡單建立一個Servlet
@WebServlet(urlPatterns = "/demo",name = "demo")
public class Demo implements Servlet {
/**
* 最開始被調用,初始化servlet,初始化一次之後不再被調用;是以servlet是一個單例線程不安全的對象。
* @param config
* @throws ServletException
*/
@Override
public void init(ServletConfig config) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 邏輯處理方法,接收響應,處理請求,具體的實作在此方法中
* @param req
* @param res
* @throws ServletException
* @throws IOException
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
}
@Override
public String getServletInfo() {
return null;
}
/**
* 調用此方法銷毀servlet
*/
@Override
public void destroy() {
}
}
元件調用順序
三大元件初始化順序與銷毀順序
初始化:Listener->Filter->Servlet
銷毀:Servlet->Filter->Listener