前言:一句話歸納啓動的順序html
context param上下文參數——>listener監聽器——>filter過濾器——>servlet——>intercept攔截器java
生命週期web
context-param上下文參數spring
當容器tomcat啓動的時候會讀取web.xml中的<context-param>標籤和<listener>標籤並初始化ServletContext(上下文)對象(ServletContext表明當前web項目,當前web項目中的全部內容都共享此對象)編程
而後容器tomcat將<context-param>中的內容解析爲鍵值對賦予ServletContext(這也就是爲何咱們能夠經過context-param的鍵得到context-param的值)瀏覽器
以後容器建立<listener></listener>中的類實例,即建立監聽器,在監聽中會有contextInitialized(ServletContextEvent args)初始化方法,經過在這個方法中的參數得到ServletContext = ServletContextEvent.getServletContext();緩存
最後獲得context-param的值 = ServletContext.getInitParameter("context-param的鍵");tomcat
listener監聽器獲得參數後就能夠進行換句話說,這個時候,對<context-param>中的鍵值對作的操做,將在的WEB項目徹底啓動以前被執行,常經過在web.xml中的配置來加載spring的配置文件服務器
<listener> <!-- 繼承於ServletContextListener,在tomcat啓動和關閉時會調用 --> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <!-- 要讀取到servletContext容器中的spring配置文件的路徑 --> <param-value>classpath:ApplicationContext.xml</param-value>
</context-param>
listener監聽器session
根據執行的時機不一樣劃分,經常使用的監聽器一共有三類,都是繼承於父接口EventListener的子接口
ServletContextListener接口
Tomcat啓動和關閉時調用的監聽器,也就是說在tomcat啓動時建立,tomcat關閉時銷燬
HttpSessionListener接口
開始會話和結束會話時調用的監聽器,也就是說開啓session時建立,session失效時銷燬
關於session失效有兩種狀況,一種是session.invalidate()方法註銷session,另外一種是超過了session的存活時間,tomcat中默認是30分鐘,能夠到tomcat/conf/web.xml文件中更改設置
ServletRequestListener接口
開始請求和結束請求時調用的監聽器,也就是說接收request請求時建立,完成request請求後銷燬
filter過濾器
init(FilterConfig):在服務器啓動時會建立Filter實例,而且每一個類型的Filter只建立一個實例,今後再也不建立!在建立完Filter實例後,會立刻調用init()方法完成初始化工做,這個方法只會被執行一次;
doFilter(ServletRequest req,ServletResponse res,FilterChain chain):這個方法會在用戶每次訪問指定過濾範圍時都會執行doFileter,若是須要「放行」,那麼須要調用FilterChain的doFilter(ServletRequest,ServletResponse)方法,若是不調用FilterChain的doFilter()方法,那麼目標資源將沒法執行;
destroy():服務器會在建立Filter對象以後,把Filter放到緩存中一直使用,一般不會銷燬它。通常會在服務器關閉時銷燬Filter對象,在銷燬Filter對象以前,服務器會調用Filter對象的destory()方法。
servlet
默認在第一次接受瀏覽器請求時建立servlet實例對象,在tomcat關閉時銷燬
javax.servlet.Servlet接口中,有三個方法說明了Servlet的生命週期:
void init(ServletConfig):建立後立刻調用init()完成初始化;
void service(ServletRequest,ServletResponse):每次處理請求時調用service()方法;
void destroy():當Tomcat要銷燬Servlet實例時,先調用destroy()方法;
能夠在web.xml文件中將servlet的建立時機改成和服務器同步
interceptor攔截器
和過濾器相似,可是隻攔截用戶對action的請求,tomcat啓動時建立,攔截到用戶對action的請求時執行前置攔截器棧,放行後執行action邏輯並返回頁面視圖,最後再執行後置攔截器棧進行收尾工做
void init():建立後立刻調用init()完成初始化;
String intercept(ActionInvocation invocation):經過invocation.invoke()方法繼續執行攔截器棧中的其餘攔截器
void destroy():當Tomcat要銷燬Interceptor實例時,先調用destroy()方法;
前置攔截——>action——>頁面執行——>後置攔截
實際應用
過濾器filter
過濾掉非法url(不是login.do的地址請求,若是用戶沒有登錄都過濾掉),或者在傳入servlet或者 struts的action前統一設置字符集, 或者去除掉一些非法字符(聊天室常常用到的,一些罵人的話)。
最經常使用的過濾器就是登錄過濾器LoginFilter,過濾器通常都是繼承Filter 接口
監聽器listener
當你要觸發一個事件,但這件事既不是過濾,又不是攔截,那極可能就是監聽。 聯想到Windows編程裏的,單擊鼠標、改變窗口尺寸、按下鍵盤上的一個鍵都會使Windows發送一個消息給應用程序。監聽器的概念相似於這些。
上下文參數context-param
用來存儲要應用在web項目全局中的參數
servlet
用來處理tomcat等容器解析後的請求
攔截器interceptor:
進行權限驗證,或者是來判斷用戶是否登錄,日誌記錄,或者限制時間點訪問。我本身用過攔截器,是用戶每次登陸時,都能記錄一個登陸時間。 (這點用攔截器明顯合適,用過濾器明顯不合適,由於沒有過濾任何東西)
做用範圍
代碼和配置
context-param 要讀取到servletContext中的配置文件+web.xml配置
listener,filter,servlet java類+web.xml配置
interceptor java類+struts.xml配置
context-param上下文參數
context-param在web.xml文件中配置要讀取的xml文件路徑便可,通常都是讀取spring的ApplicationContext.xml文件
<listener> <!-- 繼承於ServletContextListener,在tomcat啓動和關閉時會調用 --> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <!-- 要讀取到servletContext容器中的spring配置文件的路徑 --> <param-value>classpath:ApplicationContext.xml</param-value> </context-param>
listener監聽器
java類:根據監聽範圍需求的不一樣實現ServletContextListener或HttpSessionListener或ServletRequestListener三者之一
package com.rl.listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; /** * 自定義監聽器實現了ServletContextListener接口,也會在服務器啓動時初始化 */ public class MyServletContextListener implements ServletContextListener { /** * 服務器中止時銷燬 */ public void contextDestroyed(ServletContextEvent sce) { System.out.println("MyServletContextListener被銷燬"); } /** * 服務器啓動時建立 */ public void contextInitialized(ServletContextEvent sce) { System.out.println("MyServletContextListener被建立"); ServletContext sc = sce.getServletContext(); } }
配置listener:在web.xml文件中配置listener類的路徑便可
<listener> <!--指定做爲監聽器的類--> <listener-class>com.rl.listener.MyRequestListener</listener-class> </listener>
filter過濾器
java類:做爲過濾器的類要實現Filter接口
package com.rl.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; public class HelloFilter implements Filter { /** * 當服務器關閉當前方法被調用,實例被銷燬 */ public void destroy() { System.out.println("過濾器被銷燬..."); } /** * 過濾器的執行方法 */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("過濾器開始...."); //讓過濾器往下走,放行,若是後面還有過濾器,那麼就執行下一個過濾器,若是是最後一個過濾器就去執行Controller chain.doFilter(request, response); System.out.println("過濾器結束...."); } /** * 當服務器啓動的時候被執行,說明過濾器的實例是在服務器啓動時被建立的 */ public void init(FilterConfig filterConfig) throws ServletException { System.out.println("過濾器被建立..."); } }
配置filter:filter要在web.xml文件中配置filter類的路徑和filter過濾的範圍
<filter> <filter-name>helloFilter</filter-name> <!--指定做爲過濾器的類--> <filter-class>com.rl.filter.HelloFilter</filter-class> </filter> <filter-mapping> <filter-name>helloFilter</filter-name> <!--過濾器過濾的範圍--> <url-pattern>/*</url-pattern> </filter-mapping>
servlet
java類:實現Servlet接口或繼承HttpServlet類(HttpServlet的父類GenericServlet實現了Servlet接口)
package com.rl.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * doGet是給get方式的http的請求作相應的 * doPost是給post方式的http的請求作相應的 */ public class HttpServletDemo extends HttpServlet { @Override public void init() throws ServletException { System.out.println("HttpServletDemo實例被建立了"); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doGet方法被調用了"); resp.getOutputStream().write("doGet方法被調用了".getBytes()); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("doPost方法被調用了"); doGet(req, resp); } }
配置servlet:要在web.xml文件中配置servlet類的路徑和servlet的瀏覽器訪問路徑
<servlet> <!-- 設置servlet的名字 --> <servlet-name>helloServlet</servlet-name> <!-- 具體的servlet的類 --> <servlet-class>com.rl.servlet.ServletDemo1</servlet-class> <!-- 將servlet的啓動時機設置爲和服務器同步 --> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <!-- 指定要映射 的servlet的名字 --> <servlet-name>helloServlet</servlet-name> <!-- servlet的具體映射路徑 --> <url-pattern>/hello</url-pattern> </servlet-mapping>
interceptor過濾器
java類:做爲Interceptor攔截器的類要繼承於AbstractInterceptor類或繼承於MethodFilterInterceptor,要想排除對指定的action的攔截,就必定要繼承MethodFilterInterceptor類(它的父類也是AbstractInterceptor)
package com.rl.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class MyInterceptor extends AbstractInterceptor { @Override public void init() { System.out.println("建立攔截器"); } @Override public void destroy() { System.out.println("銷燬攔截器"); } @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("前置攔截執行...."); //讓攔截器向下走而且返回結果代碼 String result = invocation.invoke(); System.out.println("後置攔截執行..."); return result; } }
要攔截的action類
package com.rl.action; import com.opensymphony.xwork2.ActionSupport; /** * 擔當控制層的Action動做類 */ public class PersonAction2 extends ActionSupport{ public String savePerson(){ System.out.println("新增Person"); return super.SUCCESS; } public String deletePerson(){ System.out.println("刪除Person"); return super.SUCCESS; } }
interceptor配置:牢記在interceptor標籤中,action要放在其餘標籤的後面,否則會報錯
<package name="testInterceptor" extends="struts-default" namespace="/person"> <interceptors> <!-- 配置咱們本身的攔截器 --> <interceptor name="myInterceptor" class="com.rl.interceptor.MyInterceptor"></interceptor> <!-- 配置咱們本身的攔截器棧 --> <interceptor-stack name="myStack"> <!-- 默認的攔截器棧 --> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="myInterceptor"></interceptor-ref> </interceptor-stack> </interceptors> <!-- 包內默認攔截器棧設置爲咱們本身的myStack --> <default-interceptor-ref name="myStack"></default-interceptor-ref> <action name="*" class="com.rl.action.PersonAction2" method="{1}Person"> <result name="success">/success.jsp</result> </action> </package>
參考連接:
過濾器,攔截器,監聽器具體應用上的區別 - 阿里雲 https://yq.aliyun.com/ziliao/365762
session會話過時時間設置 https://blog.csdn.net/zqd_java/article/details/53687954
web.xml的配置中<context-param>配置做用 https://www.cnblogs.com/jiaguozhilian/p/5819032.html
struts.xml文件中package標籤中的子標籤順序 https://blog.csdn.net/lc448986375/article/details/8027150
servlet百度百科 https://baike.baidu.com/item/servlet/477555?fr=aladdin