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

一:Session管理:

必要性:

 http 是无状态的,在默认的情况下Web服务器是不知道一个Http请求是来自初次用户,还是来自之前已经访问过的用户。所以就当用户登入后是没必要再次登入。应用程序需要记住哪些用户是登入过的。

保持状态的4种方法:

1、URL重写:Session的追踪技术,需要将一个或者多个的token作为一个查询字符串添加到一个URL中。
2、隐藏域:将值保存在HTML页面的隐藏域中当用户提交表单时,隐藏域中的值也传送到服务器中。
3、cookie:cookie是作为Http标头嵌入的,所以传输过程是Http协议处理的当浏览器从服务器上请求 web 页面时, 属于该页面的 cookie 会被添加到该请求中。服务端通过这种方式来获取用户的信息。但是用户可以通过修改浏览器设置来拒绝接受Cookie。
4、HttpSession:HttpSession 保存的值不发送到客户端,Servelt容器会为它创建一个唯一的表识符,并将这个表识符作为token发送给浏览器,一般是作为一个JSESSIONID的cookie,或者作为一个jsessionid参数添加到URL后面。后续请求浏览器会将这个token发送回服务器。

二:Servlet的监听器

三个不同级别的监听对象:ServletContext、HttpSession、ServletRequest

ServletContext的监听器:

 1、ServletContextListener:能监听ServletContext一生中的两个关键事件:初始化(创建)和撤销;

public interface ServletContextListener extends EventListener {
    //ServletContext初始化时调用
    public void contextInitialized(ServletContextEvent sce);
   
   //ServletContext被撤销时调用
    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:当ServletContext范围内的属性被添加删除,替换时,这些对应的监听器将会被触发。

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监听器

 HttpSessionListener:用来监听HttpSession对象的创建和销毁。

public interface HttpSessionListener extends EventListener {
    //创建时调用
    public void sessionCreated(HttpSessionEvent se);
  //销毁时调用
    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:当Session中的属性被添加删除,替换时,这些对应的监听器将会被触发。

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:实现此接口的JavaBean,可以感知自己被活化(从硬盘到内存)和钝化(从内存到硬盘)的过程。

案例:

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对象实现了HttpSessionBindingListener接口,当这个对象被绑定到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的监听器:

 ServletReqeustListener:用来监听ServletReqeust对象的创建和销毁。在Servlet容器中是通过池来重用ServletRequest的,创建ServletRequest花费的时间是从池中获取ServletRequest的时间,ServletRequest销毁相当于把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:当ServletRequest中的属性被添加删除,替换时,这些对应的监听器将会被触发。

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启动服务时,Servlet容器会调用初始化代码
    public void init(FilterConfig filterConfig) throws ServletException;

    //每次http请求,filter进行拦截都会执行
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    //过滤器终止服务
    public void destroy();

}

过滤器拦截流程:

1、当客户端发生请求后,在HttpServletRequest 到达Servlet 之前,过滤器拦截客户的HttpServletRequest 。
2、根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
3、在过滤器中调用doFilter方法,对请求放行。请求到达Servlet后,对请求进行处理并产生HttpServletResponse发送给客户端。
4、在HttpServletResponse 到达客户端之前,过滤器拦截HttpServletResponse 。
5、根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。
6、最后,HttpServletResponse到达客户端。

FilterConfig(过滤器的配置)
四、FilterChain

 在一个Web应用程序中可以注册多个Filter程序,每个Filter程序都可以对一个或一组Servlet程序进行拦截。FilterChain其实就是一条过滤器链

Servlet容器的初始化

 容器的初始化的核心是javax.servlet.ServletContainerInitializer接口,

package javax.servlet;
 
import java.util.Set;
 
/**
 * 目的:Servlet容器初始化(ServletContainerInitializer初始化器)
 * 
 * <p>web容器启动时,调用该接口的实现(初始化器),
 * 初始化已被注册的servlets、filters、listeners。
 * 
 * <p>{@link javax.servlet.annotation.HandlesTypes HandlesTypes}注解
 * 来实现该接口,注解的类作为onStartup()方法的参数传入。
 * 
 * <p>没有@HandlesTypes注解或没有指定应用程序类匹配的注解时,容器{@link #onStartup}必须是个null集合
 * 
 * <p>实现该接口就必须在对应的jar包的META-INF/services
 * 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,
 * 该文件内容指定该接口的具体实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。
 * 
 * 实现机制:
 * Tomcat容器的ServletContainerInitializer机制的实现,主要交由Context容器
 * 和ContextConfig监听器共同实现,ContextConfig监听器负责在容器启动时读取每个web
 * 应用的WEB-INF/lib目录下包含的jar包的META-INF/services/javax.servlet.
 * ServletContainerInitializer,以及web根目录下的META-INF/services/
 * javax.servlet.ServletContainerInitializer,通过反射完成这些
 * ServletContainerInitializer的实例化,然后再设置到Context容器中,最后
 * Context容器启动时就会分别调用每个ServletContainerInitializer的onStartup方法,
 * 并将感兴趣的类作为参数传入。
 * 参考资料: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具体实例后,并设置到ServletContext中
     * @param c 实现该接口的具体实现类
     * @param ctx ServletContext
     * @throws ServletException if an error has occurred
     */
    public void onStartup(Set<Class<?>> c, ServletContext ctx)
        throws ServletException; 
}

1、Servlet容器启动会扫描,当前应用里面每一个jar包的
ServletContainerInitializer的实现
2、提供ServletContainerInitializer的实现类;
必须绑定在,META-INF/services/javax.servlet.ServletContainerInitializer
文件的内容就是ServletContainerInitializer实现类的全类名;
3、可以给ServletContainerInitializer 的实现类添加@HandlesTypes可以将感兴趣的一些类注入到ServletContainerInitializerde的onStartup方法作为参数传入。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容