一:Session管理:
必要性:
?http 是無狀態(tài)的,在默認的情況下Web服務(wù)器是不知道一個Http請求是來自初次用戶,還是來自之前已經(jīng)訪問過的用戶。所以就當(dāng)用戶登入后是沒必要再次登入。應(yīng)用程序需要記住哪些用戶是登入過的。
保持狀態(tài)的4種方法:
1、URL重寫:Session的追蹤技術(shù),需要將一個或者多個的token作為一個查詢字符串添加到一個URL中。
2、隱藏域:將值保存在HTML頁面的隱藏域中當(dāng)用戶提交表單時,隱藏域中的值也傳送到服務(wù)器中。
3、cookie:cookie是作為Http標(biāo)頭嵌入的,所以傳輸過程是Http協(xié)議處理的當(dāng)瀏覽器從服務(wù)器上請求 web 頁面時, 屬于該頁面的 cookie 會被添加到該請求中。服務(wù)端通過這種方式來獲取用戶的信息。但是用戶可以通過修改瀏覽器設(shè)置來拒絕接受Cookie。
4、HttpSession:HttpSession 保存的值不發(fā)送到客戶端,Servelt容器會為它創(chuàng)建一個唯一的表識符,并將這個表識符作為token發(fā)送給瀏覽器,一般是作為一個JSESSIONID的cookie,或者作為一個jsessionid參數(shù)添加到URL后面。后續(xù)請求瀏覽器會將這個token發(fā)送回服務(wù)器。
二:Servlet的監(jiān)聽器
三個不同級別的監(jiān)聽對象:ServletContext、HttpSession、ServletRequest
ServletContext的監(jiān)聽器:
?1、ServletContextListener:能監(jiān)聽ServletContext一生中的兩個關(guān)鍵事件:初始化(創(chuàng)建)和撤銷;
public interface ServletContextListener extends EventListener {
//ServletContext初始化時調(diào)用
public void contextInitialized(ServletContextEvent sce);
//ServletContext被撤銷時調(diào)用
public void contextDestroyed(ServletContextEvent sce);
}
//事件
public class ServletContextEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
public ServletContextEvent(ServletContext source) {
super(source);
}
public ServletContext getServletContext() {
return (ServletContext) super.getSource();
}
}
?2、ServletContextAttributeListener:當(dāng)ServletContext范圍內(nèi)的屬性被添加刪除,替換時,這些對應(yīng)的監(jiān)聽器將會被觸發(fā)。
public interface ServletContextAttributeListener extends EventListener {
//添加
public void attributeAdded(ServletContextAttributeEvent scae);
//刪除
public void attributeRemoved(ServletContextAttributeEvent scae);
//替換
public void attributeReplaced(ServletContextAttributeEvent scae);
}
//事件
public interface ServletContextAttributeListener extends EventListener {
public void attributeAdded(ServletContextAttributeEvent scae);
public void attributeRemoved(ServletContextAttributeEvent scae);
public void attributeReplaced(ServletContextAttributeEvent scae);
}
Session監(jiān)聽器
?HttpSessionListener:用來監(jiān)聽HttpSession對象的創(chuàng)建和銷毀。
public interface HttpSessionListener extends EventListener {
//創(chuàng)建時調(diào)用
public void sessionCreated(HttpSessionEvent se);
//銷毀時調(diào)用
public void sessionDestroyed(HttpSessionEvent se);
}
//事件
public class HttpSessionEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
public HttpSessionEvent(HttpSession source) {
super(source);
}
public HttpSession getSession() {
return (HttpSession) super.getSource();
}
}
?2、HttpSessionAttributeListener:當(dāng)Session中的屬性被添加刪除,替換時,這些對應(yīng)的監(jiān)聽器將會被觸發(fā)。
public interface HttpSessionAttributeListener extends EventListener {
//添加
public void attributeAdded(HttpSessionBindingEvent se);
//移除
public void attributeRemoved(HttpSessionBindingEvent se);
//替換
public void attributeReplaced(HttpSessionBindingEvent se);
}
//事件
public class HttpSessionBindingEvent extends HttpSessionEvent {
private static final long serialVersionUID = 1L;
private final String name;
private final Object value;
public HttpSessionBindingEvent(HttpSession session, String name) {
super(session);
this.name = name;
this.value = null;
}
public HttpSessionBindingEvent(HttpSession session, String name,
Object value) {
super(session);
this.name = name;
this.value = value;
}
@Override
public HttpSession getSession() {
return super.getSession();
}
public String getName() {
return name;
}
public Object getValue() {
return this.value;
}
}
?3、HttpSessionActivationListener:實現(xiàn)此接口的JavaBean,可以感知自己被活化(從硬盤到內(nèi)存)和鈍化(從內(nèi)存到硬盤)的過程。
案例:
public class Person implements Serializable, HttpSessionActivationListener {
private String name;
public Person(String name) {
super();
this.name = name;
}
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println(this + "保存到硬盤了...");
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println(this + "從硬盤讀取并活化了...");
}
@Override
public String toString() {
return "Perosn [name=" + name + "]---"+super.toString();
}
}
?4、HttpSessionBindingListener對象實現(xiàn)了HttpSessionBindingListener接口,當(dāng)這個對象被綁定到Session中或者從session中被刪除時,Servlet容器會通知這個對象;
案例:
public class UsersOnlineCountListener implements HttpSessionBindingListener {
int uid;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
@Override
public void valueBound(HttpSessionBindingEvent arg0) {
System.out.println(uid+"登錄了"+new Date());
}
@Override
public void valueUnbound(HttpSessionBindingEvent arg0) {
System.out.println(uid+"下線了"+new Date());
}
}
ServletRequest的監(jiān)聽器:
?ServletReqeustListener:用來監(jiān)聽ServletReqeust對象的創(chuàng)建和銷毀。在Servlet容器中是通過池來重用ServletRequest的,創(chuàng)建ServletRequest花費的時間是從池中獲取ServletRequest的時間,ServletRequest銷毀相當(dāng)于把ServletRequest還回池中的時間。
public interface ServletRequestListener extends EventListener {
//銷毀
public void requestDestroyed (ServletRequestEvent sre);
//初始化
public void requestInitialized (ServletRequestEvent sre);
}
//事件
public class ServletRequestEvent extends java.util.EventObject {
private static final long serialVersionUID = 1L;
private final transient ServletRequest request;
public ServletRequestEvent(ServletContext sc, ServletRequest request) {
super(sc);
this.request = request;
}
public ServletRequest getServletRequest() {
return this.request;
}
public ServletContext getServletContext() {
return (ServletContext) super.getSource();
}
}
? ServletRequestAttributeListener:當(dāng)ServletRequest中的屬性被添加刪除,替換時,這些對應(yīng)的監(jiān)聽器將會被觸發(fā)。
public interface ServletRequestAttributeListener extends EventListener {
//添加
public void attributeAdded(ServletRequestAttributeEvent srae);
//移除
public void attributeRemoved(ServletRequestAttributeEvent srae);
//替換
public void attributeReplaced(ServletRequestAttributeEvent srae);
}
三:過濾器Filter
過濾器主要接口: Filter、FilterConfig、FilterChain
Filter
public interface Filter {
//Servlet啟動服務(wù)時,Servlet容器會調(diào)用初始化代碼
public void init(FilterConfig filterConfig) throws ServletException;
//每次http請求,filter進行攔截都會執(zhí)行
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
//過濾器終止服務(wù)
public void destroy();
}
過濾器攔截流程:
1、當(dāng)客戶端發(fā)生請求后,在HttpServletRequest 到達Servlet 之前,過濾器攔截客戶的HttpServletRequest 。
2、根據(jù)需要檢查HttpServletRequest ,也可以修改HttpServletRequest 頭和數(shù)據(jù)。
3、在過濾器中調(diào)用doFilter方法,對請求放行。請求到達Servlet后,對請求進行處理并產(chǎn)生HttpServletResponse發(fā)送給客戶端。
4、在HttpServletResponse 到達客戶端之前,過濾器攔截HttpServletResponse 。
5、根據(jù)需要檢查HttpServletResponse ,可以修改HttpServletResponse 頭和數(shù)據(jù)。
6、最后,HttpServletResponse到達客戶端。
FilterConfig(過濾器的配置)
四、FilterChain
?在一個Web應(yīng)用程序中可以注冊多個Filter程序,每個Filter程序都可以對一個或一組Servlet程序進行攔截。FilterChain其實就是一條過濾器鏈
Servlet容器的初始化
?容器的初始化的核心是javax.servlet.ServletContainerInitializer接口,
package javax.servlet;
import java.util.Set;
/**
* 目的:Servlet容器初始化(ServletContainerInitializer初始化器)
*
* <p>web容器啟動時,調(diào)用該接口的實現(xiàn)(初始化器),
* 初始化已被注冊的servlets、filters、listeners。
*
* <p>{@link javax.servlet.annotation.HandlesTypes HandlesTypes}注解
* 來實現(xiàn)該接口,注解的類作為onStartup()方法的參數(shù)傳入。
*
* <p>沒有@HandlesTypes注解或沒有指定應(yīng)用程序類匹配的注解時,容器{@link #onStartup}必須是個null集合
*
* <p>實現(xiàn)該接口就必須在對應(yīng)的jar包的META-INF/services
* 目錄創(chuàng)建一個名為javax.servlet.ServletContainerInitializer的文件,
* 該文件內(nèi)容指定該接口的具體實現(xiàn)類,那么,當(dāng)web容器啟動時就會運行這個初始化器做一些組件內(nèi)的初始化工作。
*
* 實現(xiàn)機制:
* Tomcat容器的ServletContainerInitializer機制的實現(xiàn),主要交由Context容器
* 和ContextConfig監(jiān)聽器共同實現(xiàn),ContextConfig監(jiān)聽器負責(zé)在容器啟動時讀取每個web
* 應(yīng)用的WEB-INF/lib目錄下包含的jar包的META-INF/services/javax.servlet.
* ServletContainerInitializer,以及web根目錄下的META-INF/services/
* javax.servlet.ServletContainerInitializer,通過反射完成這些
* ServletContainerInitializer的實例化,然后再設(shè)置到Context容器中,最后
* Context容器啟動時就會分別調(diào)用每個ServletContainerInitializer的onStartup方法,
* 并將感興趣的類作為參數(shù)傳入。
* 參考資料:http://blog.csdn.net/wangyangzhizhou/article/details/52013779
*
* @author TCM
* @create 2017年10月24日上午9:55:01
* @see javax.servlet.annotation.HandlesTypes
* @since Servlet 3.0
*/
public interface ServletContainerInitializer {
/**
* 啟動ServletContainerInitializer具體實例后,并設(shè)置到ServletContext中
* @param c 實現(xiàn)該接口的具體實現(xiàn)類
* @param ctx ServletContext
* @throws ServletException if an error has occurred
*/
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
1、Servlet容器啟動會掃描,當(dāng)前應(yīng)用里面每一個jar包的
ServletContainerInitializer的實現(xiàn)
2、提供ServletContainerInitializer的實現(xiàn)類;
必須綁定在,META-INF/services/javax.servlet.ServletContainerInitializer
文件的內(nèi)容就是ServletContainerInitializer實現(xiàn)類的全類名;
3、可以給ServletContainerInitializer 的實現(xiàn)類添加@HandlesTypes可以將感興趣的一些類注入到ServletContainerInitializerde的onStartup方法作為參數(shù)傳入。