servlet 是基于 Java 的 Web 组件,由容器进行管理,来生成动态内容。像其他基于 Java 的组件技术一样,servlet 也是基于平台无关的 Java 类格式,被编译为平台无关的字节码,可以被基于 Java 技术的 Web 服务器动态加载并运行。容器(Container),有时候也叫做 servlet 引擎,是 Web 服务器为支持 servlet 功能扩展的部分。客户端通过 servlet 容器实现的 request/response paradigm(请求/应答模式) 与 Servlet 进行交互。

目录

1.规约概述

1.1. 整体结构图

1.2. Servlet接口

1.3. ServletRequest接口

1.4. ServletContext接口

1.5. ServletResponse接口

1.6. Filter接口

1.7. 会话

1.8. 注解

1.9. 可插拔

1.10. 请求分发器

1.11.Web应用

1.12. 应用生命周期事件

1.13.Servlet映射

1.14.部署描述文件

1.15. 安全

2.各版本与tomcat的关联

3.参考资料


1.规约概述

1.1. 整体结构图

快速掌握Servlet规约_java

快速掌握Servlet规约_Web_02

1.2. Servlet接口

快速掌握Servlet规约_java_03

Servlet接口是核心接口,Java Servelt API中已经提供了两个抽象类方便开发者实现Servlet类,分别是GenericServlet 和 HttpServlet,GenericServlet定义了一个通用的、协议无关的Servlet,而HttpServlet则定义了Http协议的Servlet,这两个抽象类可以使Servlet类复用很多共性功能。

核心方法service方法,它作为处理客户端请求的处理方法,客户端发起的请求会被路由到对应的Servlet对象上,前面说到的HttpServlet类的service方法即为对http协议的GET、POST、PU、DELETE、HEAD、OPTIONS、TRACE等请求转发到各自处理方法中,对应着doGet、doPost、doPut、doDelete、doHead、doOptions、doTrace等方法,HTTPServlet提供了这些共性的处理逻辑。

Servlet的生命周期主要包括加载实例化、初始化、处理客户端请求、销毁。加载实例化主要是交由web容器完成,而其他三个阶段则对应Servlet的init、service和destroy方法。

1.3. ServletRequest接口

快速掌握Servlet规约_java_04

ServletRequest接口的实现类封装了客户端请求的所有信息,如果使用HTTP协议通信则包括HTTP协议的请求行和请求头。HTTP协议对应请求对象类型是HttpServletRequest类。

  • 它提供了一些HTTP协议请求头部的获取方法,如getHeader、getHeaders和getHeaderNames;
  • 它提供了一些获取请求路径的方法,如getContextPath、getServletPath和getPathInfo,对于路径变量,其中requestURI=contextPath+servletPath+pathInfo,而getRealPath方法则是获取某个相对路径对应的文件系统路径;
  • 它提供了获取cookie的方法,如getCookies方法;提供了标识是否为HTTPS协议的方法,如isSecure方法;
  • 它提供了获取客户端的语言环境的方法,如getLocale和getLocales,它们对应Http协议的Accept-Language头部;
  • 它提供了获取客户端编码的方法,如getCharacterEncoding,对应http协议的 Content-Type头部。

ServletRequest接口的对象只在servlet的service方法或过滤器的doFilter方法作用域内有效,除非启用了异步处理调用了ServletRequest接口对象的startAsync方法,此时request对象会一直有效,直到调用AsyncContext的complete方法。另外,web容器通常会为了性能而不销毁ServletRequest接口的对象,而是重复利用ServletRequest接口对象。

1.4. ServletContext接口

ServletContext接口定义了运行了所有Servlet的web应用的视图。

  • 它提供某个web应用的Servlet全局存储空间,某web应用对应的所有Servlet共有的各种资源和功能的访问。
  • 它提供了获取web应用的部署描述配置文件的方法,例如getInitParameter和getInitParameterNames;
  • 它提供了添加Servlet到ServletContext里面的方法,例如addServlet;
  • 它提供了添加Filter过滤器到ServletContext里面的方法,例如addFilter;
  • 它提供了添加Listener监听器到ServletContext里面的方法,例如addListener;
  • 它提供全局的属性保存和获取功能,例如setAttribute、getAttribute、getAttributeNames和removeAttribute等;

所有Servlet及它们使用的类需要由一个单独的类加载器加载。每个实现ServletContext接口的对象都需要一个临时存储目录,Servlet容器必须为每个ServletContext分配一个临时目录,并可在ServletContext接口通过 javax.servlet.context.tempdir属性获取该目录。

1.5. ServletResponse接口

快速掌握Servlet规约_Web_05

ServletResponse接口的对象封装了服务端要返回客户端的所有信息,如果是HTTP协议则包含了http的响应行、响应头和响应体。

为了提高效率,一般ServletResponse接口对响应提供了输出缓冲,其中getBufferSize用于获取缓冲区大小,setBufferSize用于设置缓冲区大小,flushBuffer强制刷出缓冲区,resetBuffer将清空缓冲区中的内容,但不清空请求头和状态码,isCommitted判断是否有任何响应字节已经返回给客户端,reset清空缓冲区内容,同时清空头信息和状态码。

当ServletResponse接口关闭时,缓冲区中的内容必须立即刷到客户端,ServletResponse接口只在Servlet的service方法或过滤器的doFilter方法作用域内有效,除非它关联的ServletResponse接口调用了startAsync方法启用异步处理,此时ServletResponse接口会一直有效,直到调用AsyncContext的complete方法。另外,web容器通常会为了性能而不销毁ServletResponse接口对象,而是重复利用ServletResponse接口对象。

1.6. Filter接口

Filter接口允许Web容器对请求和响应做统一处理,例如统一改变HTTP请求内容和响应内容,它可以作用在某个Servlet或一组Servlet。

Web应用部署完成后,必须实例化好过滤器并调用其init方法,当请求进来时,获取第一个过滤器并调用doFilter方法,并传入ServletRequest对象、ServletResponse对象及过滤链FilterChain,doFilter方法负责过滤器链的下个实体的doFilter方法调用。当容器要移除某过滤器时必须先调用过滤器的destroy方法。

可以用“@WebFilter”注解或部署描述文件定义过滤器,XML配置形式使用元素定义,包括、和子节点,并使用定义web应用的Servlet和其他静态资源通过过滤器。

1.7.

Servlet没有提出协议无关的会话规定,而是每个通信协议自己规定,HTTP协议对应的会话接口是HttpSession。Cookie是常用的会话跟踪机制,其中Cookie的标准名字必须为JSESSIONID。另外一种会话跟踪机制则是URL重写,即在URL后面添加一个jsessionid参数,当支持Cookie和SSL会话的情况下不应该使用URL重写作为会话跟踪机制。会话 ID 通过调用 HttpSession.getId()获取,且能在创建后通过调用HttpServletRequest.changeSessionId()改变。HttpSession对象必须限定在ServletContext级别,会话里面的属性不能在不同ServletContext之间共享。

Servlet可将某对象以键值对形式保存到HttpSession中,处于同个ServletContext且相同会话的任意Servlet都可以使用会话中保存的对象。如果某些对象想要在保存到会话或从会话中移除时得到通知,可以让某个对象实现HttpSessionBindingListener接口,里面的valueBound和valueUnbound分别会在对应时刻被触发。

Servlet容器默认会话超时时间,可以通过HttpSession的getMaxInactiveInterval方法获取和setMaxInactiveInterval 方法设置。
分布式环境中,会话的所有请求在同一时间必须仅被一个JVM处理,分布式容器迁移会话时会通知实现了HttpSessionActivationListener接口的所有会话属性。

1.8. 注解

web应用中,使用了注解的类只有被放到WEB-INF/classes目录中或WEB-INF/lib目录下的jar中注解才会被Web容器处理。web.xml配置文件的元素的metadata-complete默认为false,表示Web容器必须检查类的注解和web fragments,否则忽略注解和web fragments。

javax.servlet.ServletContextListener
javax.servlet.ServletContextAttributeListener
javax.servlet.ServletRequestListener
javax.servlet.ServletRequestAttributeListener
javax.servlet.http.HttpSessionListener
javax.servlet.http.HttpSessionAttributeListener
javax.servlet.http.HttpSessionIdListener

  • @WebServlet注解用于在Web项目定义Servlet,必须指定urlPatterns或value属性,默认的name属性为全限定类名,@WebServlet注解的类必须继承javax.servlet.http.HttpServlet类;
  • @WebFilter注解用于在Web项目定义Filter,必须指定urlPatterns,servletNames或value属性,默认的filterName属性为全限定类名,@ WebFilter注解的类必须实现 javax.servlet.Filter;
  • @WebInitParam注解用于指定传递到Servlet或Filter的初始化参数,它是WebServlet和WebFilter注解的一个属性;
  • @WebListener注解用于定义Web应用的各种监听器,@WebListener注解的类必须实现以下接口中的其中一个:
  • @MultipartConfig注解用于指定Servlet请求期望是mime/multipart类型。

1.9. 可插拔

为了给Web开发人员提供更好的可插拔性和更少的配置,可以在一个库类或框架jar包的META-INF目录指定web fragment,即web-fragment.xml配置文件,它可以看成是Web的逻辑分区,web-fragment.xml与web.xml包含的元素基本都相同。部署期间,Web容器会扫描WEB-INF/lib目录下的jar包的META-INF/web-fragment.xml文件,并根据配置文件生成对应的组件。一个Web应用可能会有一个web.xml和若干个web-fragment.xml文件,Web容器加载时会涉及顺序问题,有两种方式定义他们加载的顺序:

  • 绝对顺序,web.xml中的元素用于描述加载资源的顺序;
  • 相对顺序,web-fragment.xml中的元素用于描述web-fragment.xml之间的顺序。

1.10. 请求分发器

请求分发器是把请求转发给另外一个Servlet处理,或在响应中包含另外一个Servlet的输出,RequestDispatcher接口提供了此实现机制。可以通过ServletContext的getRequestDispatcher方法和getNamedDispatcher方法分别通过路径或Servlet名称作为参数获取对应Servlet的RequestDispatcher。请求分发器有include和forward两个方法,include方法是将目标Servlet包含到当前的Servlet中,主控制权在当前Servlet上;forward方法是将当前Servlet的请求转移到目标Servlet上,主控权在在目标Servlet上,当前Servlet的执行终止。

1.11.Web应用

Web应用和ServletContext接口对象是一对一的关系,ServletContext 对象提供了一个 Servlet 和它的应用程序视图。Web应用可能包括Servlet、JSP、工具类、静态文件、客户端Java Applet等等,Web应用结构包括WEB-INF/web.xml文件、WEB-INF/lib/目录下存放所有jar包、WEB-INF/classes/目录存放所有类、META-INF目录存放工程的一些信息、其他资源根据具体目录存放。一般WEB-INF 目录下的文件都不能由容器直接提供给客户端访问,但WEB-INF目录中的内容可以通过 Servlet 代码调用 ServletContext 的 getResource 和 getResourceAsStream 方法来访问,并可使用 RequestDispatcher 调用公开这些内容。

Web容器用于加载WAR文件中Servlet的类加载器必须提供getResource方法用于加载WAR文件的JAR包中包含的任何资源。容器不允许Web应用程序覆盖或访问容器的实现类。一个类加载器的实现必须保证对部署到容器的每个 Web应用调用Thread.currentThread.getContextClassLoader()返回一个规定的ClassLoader实例。。部署的每个 Web 应用程序的ClassLoader实例必须是一个单独的实例。

当一个Web应用程序部署到容器中时,在Web应用程序开始处理客户端请求之前,必须按照下述步骤顺序执行:
① 实例化部署描述文件中元素标识的每个事件监听器的一个实例。
② 对于已实例化的实现了 ServletContextListener 接口的监听器实例,调用 contextInitialized()方法。
③ 实例化部署描述文件中元素标识的每个过滤器的一个实例,并调用每个过滤器实例的 init()方法。
④ 包含元素的元素,根据load-on-startup元素值定义的顺序为每个Servlet实例化一个实例,并调用每个servlet实例的init()方法
对于不包含任何Servlet、Filter或Listener的Web应用,或使用注解声明的Web应用,可以不需要web.xml部署描述符。

1.12. 应用生命周期事件

应用的事件机制给 Web 应用开发人员更好地控制 ServletContext、HttpSession 和 ServletRequest 的生命周期,可以更好地代码分解,并在管理 Web 应用使用的资源上提高了效率。

Servlet Context Events

事件类型

描述

监听器接口

生命周期

Servlet上下文刚刚创建并可用于服务它的第一个请求,或者Servlet上下文即将关闭

ServletContextListener

属性更改

在 Servlet 上下文的属性已添加、删除、或替换。

ServletContextAttributeListener

HTTP Session Events

事件类型

描述

监听器接口

生命周期

会话已创建、销毁或超时。

HttpSessionListener

属性更改

已经在HttpSession上添加、移除、或替换属性

HttpSessionAttributeListener

改变ID

HttpSession 的 ID 将被改变

HttpSessionIdListener

会话迁移

HttpSession 已被激活或钝化

HttpSessionActivationListener

对象绑定

对象已经从HttpSession绑定或解除绑定

HttpSessionBindingListener

Servlet Request Events

事件类型

描述

监听器接口

生命周期

一个servlet请求已经开始由Web组件处理

ServletRequestListener

更改属性

已经在ServletRequest上添加、移除、或替换属性。

ServletRequestAttributeListener

异步事件

超时、连接终止或完成异步处理

AsyncListener

1.13.Servlet映射

对于请求的URL,Web容器根据最长的上下文路径匹配请求URL,然后匹配Servlet,Servlet的路径是由整个请求URL减去上下文和路径参数,匹配规则如下:

  • Web容器尝试匹配一个精确的Servlet路径,成功则选择该Servlet。
  • Web容器递归尝试匹配最长路径前缀
  • 如果URL最后包含扩展名,例如.jsp,Web容器将试图匹配一个专门用于处理此扩展名的Servlet。
  • 如果前三个规则都没匹配上,则匹配一个默认的Servlet

1.14.部署描述文件

所有Servlet容器的Web应用程序部署描述文件需要支持以下类型的配置和部署信息:

①ServletContext 初始化参数
②Session 配置
③Servlet 声明
④Servlet 映射
⑤应用程序生命周期监听器类
⑥过滤器定义和过滤器映射
⑦MIME 类型映射
⑧欢迎文件列表
⑨错误页面
⑩语言环境和编码映射

1.15. 安全

应用开发人员创建Web应用,他给、销售或其他方式转入应用给部署人员,部署人员覆盖安装到运行时环境。应用开发人员与部署人员沟通部署系统的安全需求。该信息可以通过应用部署描述符声明传达,通过在应用代码中使用注解,或通过 ServletRegistration 接口的setServletSecurity 方法编程。

servlet 容器有满足这些需求的机制和基础设施,共用如下一些特性:

  • 身份认证:表示通信实体彼此证明他们具体身份的行为是被授权访问的。
  • 资源访问控制:表示和资源的交互是受限于集合的用户或为了强制完整性、保密性、或可用性约束的程序。
  • 数据完整性:表示用来证明信息在传输过程中没有被第三方修改。
  • 保密或数据隐私:表示用来保证信息只对以授权访问的用户可用。

安全配置,包括 login-config,security-constraint,security-constraint,security-role-ref 和 run-as。

2.各版本与tomcat的关联

Tomcat版本

Servlet版本

Apache Tomcat 9.x

Servlet 4.0, JSP 2.4?, EL 3.1?, Web Socket 1.2

Apache Tomcat 8.x

Servlet 3.1, JSP 2.3, EL 3.0, Web Socket 1.1

Apache Tomcat 7.x

Servlet 3.0, JSP 2.2, EL 2.2, Web Socket 1.1

Apache Tomcat 6.x

Servlet 2.5, JSP 2.1