Servlet详解



Servlet

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

Servlet生命周期

Servlet生命周期

如图:

  • 图中画出的是第一次请求Servlet的情况, 若对应的Servlet对象还没被创建, 则创建Servlet对象
  • Servlet对象只初始化一次, 只会执行一次init()方法, Servlet初始化好之后, 新请求将直接到第5步
  • 第2步中解析出的应用对应getContextPath, 资源对应getServletPath
  • 图中没画出Servlet的消亡, Servlet对象被创建后常驻内存, 继续为其他请求服务; web应用停止前调用Servletdestroy()方法, Servlet生命周期才结束

Servlet配置

  • 上面的Servlet是有第一个请求时被创建, 可以在web.xml中通过<load-on-startup>元素指定在web容器启动时就直接初始化Servlet
  • Servlet所映射的URL由<servlet-mapping>里的<url-pattern>指定, 它只有两个固定格式:
    1. *.扩展名, 如: *.do
    2. /开头(并以/*结尾), 如: /abc, /abc/*
  • URL映射以最精确的为准, 请求/abc时, 映射/abc/abc/*都可以匹配, 但优先选择/abc; 请求/a.do时, /**.do都可以匹配, 但优先选择/*(即/*优先级高于*.do)

ServletConfig

web.xml中可以使用<init-param>标签为Servlet配置一些参数. HttpServlet类也实现了ServletConfig接口, 在创建Servlet对象时先把参数封装到ServletConfig对象中, 在调用Servletinit方法时把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服务器在调用Servletservice()方法之前会调用FilterdoFilter()方法.

web服务器把所有的Filter按注册顺序组成一个filterChain, 在调用FilterdoFilter()方法时, 会传递filterChain对象进来. filterChain也有个doFilter方法, 当调用filterChain.doFilter()时, web服务器会检查filterChain中是否还有filter, 如果有, 则调用下一个filter.

Filter生命周期

Filter的创建和销毁由web服务器负责. web服务器启动时创建Filter实例对象, 并调用其init方法, 完成对象的初始化, 为用户请求作好拦截的准备. Filter对象只创建一次, init方法只执行一次. Filter也有初始化参数, 被封装到FilterConfig中, 它有个方法getServletContext()可获取ServletContext

装饰器模式(decorator)

Servlet API中体现了一种设计模式: 装饰器模式

装饰器模式的实现步骤:

  1. 先看需要被增强对象实现了什么接口或继承了什么父类, 编写一个类也去继承这些接口或父类
  2. 内部定义一个变量, 类型为被包装类的类型, 并提供一个构造函数用于接收被包装对象
  3. 覆盖需要增强的方法, 添加增强内容
  4. 实现接口中其他方法, 调用被包装对象的对应方法.

Servlet API 提供了一个HttpServletRequestWrapper类, 该类就是采用装饰器模式对HttpServletRequest进行了增强(实际上在内部仅调用了一下所包装的对象的对应方法).


Listener

全称是事件监听器EventListener, 全类名是java.util.EventListener, Servlet API中的监听器也是继承这个接口.

监听器是典型的 观察者模式 , 使用监听器要了解三个概念:

  • 事件源: 就是被监听的对象
  • 事件对象: 就是被监听的对象发生的动作, 封装成了一个事件对象. 比如增加了一个属性
  • 监听器: 对事件源发生的动作做出反应的对象. 由开发人员编写, 在事件监听器中, 可通过事件对象拿到事件源, 从而对事件源上的操作进行处理.

Servlet监听器

Servlet中的监听器不是直接注册在事件源上的, 而是由由WEB容器负责注册.

Servlet规范中定义了多种类型的监听器, 它们用于监听的事件源分别为ServletContext, HttpSessionServletRequest这三个对象.

根据监听的类型不同, 又可分为:

  • 监听事件源对象创建和销毁的事件监听器, 如: ServletContextListener, HttpSessionListener, ServletRequestListener.
  • 监听事件源对象属性添加和删除的事件监听器, 如: ServletContextAttributeListener, HttpSessionAttributeListener, ServletRequestAttributeListener.
  • 监听绑定到HttpSession中的对象的状态的事件监听器, 如: HttpSessionBindingListener, HttpSessionActivationListener, 这俩监听器比较特殊, 不需要在web.xml中进行注册