Servlet详解
Servlet
- Servlet是Sun公司提供的用于web开发的接口, 我们一般把实现了- Servlet接口的程序称为- Servlet程序
- Servlet应该由web服务器调用(比如通过配置- web.xml), 自己不能独立运行
- Servlet接口有两个实现类- HttpServlet --> GenericServlet,- HttpServlet重写了- service方法, 根据请求方式自动调用- doGet或- doPost方法, 我们一般继承这个类, 重写- doGet、doPost即可.
Servlet生命周期

如图:
- 图中画出的是第一次请求Servlet的情况, 若对应的Servlet对象还没被创建, 则创建Servlet对象
- Servlet对象只初始化一次, 只会执行一次- init()方法,- Servlet初始化好之后, 新请求将直接到第5步
- 第2步中解析出的应用对应getContextPath, 资源对应getServletPath
- 图中没画出Servlet的消亡,Servlet对象被创建后常驻内存, 继续为其他请求服务; web应用停止前调用Servlet的destroy()方法,Servlet生命周期才结束
Servlet配置
- 上面的Servlet是有第一个请求时被创建, 可以在web.xml中通过<load-on-startup>元素指定在web容器启动时就直接初始化Servlet
- Servlet所映射的URL由- <servlet-mapping>里的- <url-pattern>指定, 它只有两个固定格式:- *.扩展名, 如:- *.do
- 以/开头(并以/*结尾), 如:/abc,/abc/*
 
- URL映射以最精确的为准, 请求/abc时, 映射/abc和/abc/*都可以匹配, 但优先选择/abc; 请求/a.do时,/*和*.do都可以匹配, 但优先选择/*(即/*优先级高于*.do)
ServletConfig
在web.xml中可以使用<init-param>标签为Servlet配置一些参数. HttpServlet类也实现了ServletConfig接口, 在创建Servlet对象时先把参数封装到ServletConfig对象中, 在调用Servlet的init方法时把ServletConfig对象传给Servlet.
在Servlet类中, 我们可以获取ServletConfig中的参数
ServletConfig config = this.getServletConfig(); // 这个方法继承自GenericServlet
String value = config.getInitParameter("charset");  // 这可获取我们配置的参数ServletContext
ServletContext表示应用的上下文, 在Web容器在启动时, 会为每个Web应用程序都创建一个对应的ServletContext对象, 一个应用只有一个ServletContext对象, 被所有的Servlet共享.
ServletContext的属性可以通过web.xml中的<context-param>标签来指定, 在程序中可以这样获取这些属性:
// ServletConfig 里维护了 ServletContext 对象的引用
ServletContext context = this.getServletConfig().getServletContext();
// 因为 Servlet类实现了 ServletConfig 接口, 所以也可以直接获取
ServletContext context1 = this.getServletContext();
// 获取属性
context.getAttribute("data");
// 获取 <display-name> 标签配置的应用名
context.getServletContextName();Filter
Servlet API中提供了一个Filter接口, 称为过滤器, 所有的请求要先经过过滤器. web服务器在调用Servlet的service()方法之前会调用Filter的doFilter()方法.
web服务器把所有的Filter按注册顺序组成一个filterChain, 在调用Filter的doFilter()方法时, 会传递filterChain对象进来. filterChain也有个doFilter方法, 当调用filterChain.doFilter()时, web服务器会检查filterChain中是否还有filter, 如果有, 则调用下一个filter.
Filter生命周期
Filter的创建和销毁由web服务器负责. web服务器启动时创建Filter实例对象, 并调用其init方法, 完成对象的初始化, 为用户请求作好拦截的准备. Filter对象只创建一次, init方法只执行一次. Filter也有初始化参数, 被封装到FilterConfig中, 它有个方法getServletContext()可获取ServletContext
装饰器模式(decorator)
在Servlet API中体现了一种设计模式: 装饰器模式
装饰器模式的实现步骤:
- 先看需要被增强对象实现了什么接口或继承了什么父类, 编写一个类也去继承这些接口或父类
- 内部定义一个变量, 类型为被包装类的类型, 并提供一个构造函数用于接收被包装对象
- 覆盖需要增强的方法, 添加增强内容
- 实现接口中其他方法, 调用被包装对象的对应方法.
Servlet API 提供了一个HttpServletRequestWrapper类, 该类就是采用装饰器模式对HttpServletRequest进行了增强(实际上在内部仅调用了一下所包装的对象的对应方法).
Listener
全称是事件监听器EventListener, 全类名是java.util.EventListener, Servlet API中的监听器也是继承这个接口.
监听器是典型的 观察者模式 , 使用监听器要了解三个概念:
- 事件源: 就是被监听的对象
- 事件对象: 就是被监听的对象发生的动作, 封装成了一个事件对象. 比如增加了一个属性
- 监听器: 对事件源发生的动作做出反应的对象. 由开发人员编写, 在事件监听器中, 可通过事件对象拿到事件源, 从而对事件源上的操作进行处理.
Servlet监听器
Servlet中的监听器不是直接注册在事件源上的, 而是由由WEB容器负责注册.
在Servlet规范中定义了多种类型的监听器, 它们用于监听的事件源分别为ServletContext, HttpSession和ServletRequest这三个对象.
根据监听的类型不同, 又可分为:
- 监听事件源对象创建和销毁的事件监听器, 如: ServletContextListener, HttpSessionListener, ServletRequestListener.
- 监听事件源对象属性添加和删除的事件监听器, 如: ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener.
- 监听绑定到HttpSession中的对象的状态的事件监听器, 如:HttpSessionBindingListener, HttpSessionActivationListener, 这俩监听器比较特殊, 不需要在web.xml中进行注册
