回顧下Servlet(2)2018-08-06

一: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ù)傳入。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容