- Servlet是什么
- Servlet与tomcat关系
是什么
实现动态网站的技术早期的Web服务器,只能响应浏览器发来的HTTP静态资源的请求,并将存储在服务器中的静态资源返回给浏览器。随着Web技术的发展,逐渐出现了动态技术,为了解决web服务器不能够直接运行脚本的问题诞生了:CGI、Servlet等技术。
Java Servlet API 是Java EE技术的一部分。
方案对比:
Tomcat跟Servlet直间关系
Tomcat是应用(java)服务器,它只是一个servlet容器,是Apache的扩展,处理动态网页部分。
Servlet容器用来来管理和运行servlet,但是为什么要这样做呢?使用servlet容器的原因有:
- 通信支持
利用容器提供的方法,你能轻松的让servlet与web服务器对话,而不用自己建立serversocket、监听某个端口、创建流等 等。容器知道自己与web服务器之间的协议,所以你的servlet不用担心web服务器(如Apache)和你自己的web代码之间的API,只需要考 虑如何在servlet中实现业务逻辑(如处理一个订单)。 - 生命周期管理:
servlet容器控制着servlet的生与死,它负责加载类、实例化和初始化servlet,调用servlet方法,以及使servlet实例被垃圾回收,有了servlet容器,你不需要太多的考虑资源管理。 - 多线程支持:
容器会自动为它所接收的每个servlet请求创建一个新的java线程。针对用户的请求,如果servlet已经运行完相应的http服务方法,这个线程就会结束。这并不是说你不需要考虑线程安全性,其实你还会遇到同步问题,不过这样能使你少做很多工作。 - 声明方式实现安全:
利用servlet容器,你可以使用xml部署描述文件来配置和修改安全性,而不必将其硬编码写到servlet类代码中。 - JSP支持:
servlet容器负责将jsp代码翻译为真正的java代码。
Servlet4.0
- 支持服务器推送(HTTP/2 强化功能)
- 运行时发现servlet的URL映射
PushBuilder
1 | @Override |
- newPushBuilder() 返回一个全新对象
- newPushBuilder 可能会返回Null,当客户端不接收时
- 只支持GET方法类型
- 请求头不包含:
- 条件标头
* Range标头
* Expect 标头
* Authorization 标头
* Referrer 标头
- 条件标头
HttpServletMapping接口
Servlet 4.0 的全新 servlet 映射发现 API 使服务器能够对 URL(可调用 servlet)执行运行时检查。例如,对 file.ext, /path 和 /path/file.ext 的请求将通过 URL 模式 /path/* 和 *.ext 激活 servlet。
HttpServletMapping 接口支持运行时发现 servlet 的映射 URL。您可以在 HttpServletRequest 实例上调用 getHttpServletMapping() ,获取接口的实例。您可以使用以下方法获取有关 servlet 映射 URL 的信息:
- getMatchValue() 返回部分 URI 路径,该路径会导致请求匹配。
- getPattern() 返回 URL 模式的 String 表示形式。
- getServletName() 返回 servlet 名称的 String 表示形式。
- getMappingMatch() 返回匹配的类型,表示为 MappingMatch 枚举值,该枚举值将为以下值之一: CONTEXT_ROOT 、 DEFAULT 、 EXACT 、 EXTENSION 或 PATH 。
其他变化
除了服务器推送和全新 HttpServletMapping 接口,Servlet 4.0 还包括少量值得注意的新增功能和变更。
-
Trailer 响应标头支持发送方在分块消息的末尾包含额外字段。这用于提供在发送消息主体时可能会动态生成的元数据,例如,消息完整性检查、数字签名或后期处理状态。
-
Servlet 4.0 添加了 GenericFilter 和 HttpFilter 抽象类,这些抽象类通过最低限度地实现生命周期方法 init() 和 destroy() ,简化了编写过滤器。
-
Servlet 4.0 还集成了全新的 HTTP Trailer ,支持发送方在分块消息的末尾包含额外的字段。
-
ServletContext 接口采用了一些新方法:
- addJspFile() 可将带有给定 JSP 文件的 servlet 添加到 servlet 上下文中。
- getSessionTimeout() 和 setSessionTimeout() 可提供对会话超时的访问权限。
- getRequestCharacterEncoding() 和 setRequestCharacterEncoding() 可为当前的 servlet 上下文提供访问权限,并改变默认的请求字符编码。
-
HttpServletRequest 接口上的 * isRequestedSessionIdFromUrl() 方法已被弃用。
-
由于升级到 Java SE 8,默认方法已被添加到侦听器接口中。
Servlet3.0
Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署。
- 异步处理支持:
- 新增的注解支持
- 可插性支持
异步处理支持
1 | <servlet> |
新增的注解支持
@WebServlet
@WebServlet 用于将一个类声明为 Servlet,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为 Servlet。该注解具有下表给出的一些常用属性(以下所有属性均为可选属性,但是 vlaue 或者 urlPatterns 通常是必需的,且二者不能共存,如果同时指定,通常是忽略 value 的取值):
1 | @WebServlet(urlPatterns = {"/simple"}, asyncSupported = true, |
@WebInitParam
该注解通常不单独使用,而是配合 @WebServlet 或者 @WebFilter 使用。它的作用是为 Servlet 或者过滤器指定初始化参数,这等价于 web.xml 中 和 的 子标签。@WebInitParam 具有下表给出的一些常用属性:
@WebFilter
@WebFilter 用于将一个类声明为过滤器,该注解将会在部署时被容器处理,容器将根据具体的属性配置将相应的类部署为过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性均为可选属性,但是 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值 ):
1 | @WebFilter(servletNames = {"SimpleServlet"},filterName="SimpleFilter") |
@WebListener
该注解用于将类声明为监听器,被 @WebListener 标注的类必须实现以下至少一个接口:
- ServletContextListener
- ServletContextAttributeListener
- ServletRequestListener
- ServletRequestAttributeListener
- HttpSessionListener
- HttpSessionAttributeListener
1 | @WebListener("This is only a demo listener") |
@MultipartConfig
该注解标注在 Servlet 上面,以表示该 Servlet 希望处理的请求的 MIME 类型是 multipart/form-data。
可插性支持
Servlet 3.0 引入了称之为”Web 模块部署描述符片段”的 web-fragment.xml 部署描述文件,该文件必须存放在 JAR 文件的 META-INF 目录下,该部署描述文件可以包含一切可以在 web.xml 中定义的内容。JAR 包通常放在 WEB-INF/lib 目录下,除此之外,所有该模块使用的资源,包括 class 文件、配置文件等,只需要能够被容器的类加载器链加载的路径上,比如 classes 目录等。
三种方式增加一个(过滤器、监听器、Servlet):
- 编写一个类继承自 HttpServlet,将该类放在 classes 目录下的对应包结构中,修改 web.xml,在其中增加一个 Servlet 声明。这是最原始的方式;
- 编写一个类继承自 HttpServlet,并且在该类上使用 @WebServlet 注解将该类声明为 Servlet,将该类放在 classes 目录下的对应包结构中,无需修改 web.xml 文件。
- 编写一个类继承自 HttpServlet,将该类打成 JAR 包,并且在 JAR 包的 META-INF 目录下放置一个 web-fragment.xml 文件,该文件中声明了相应的 Servlet 配置。web-fragment.xml 文件示例如下:
1 | <?xml version="1.0" encoding="UTF-8"?> |
ServletContext 的性能增强
ServletContext支持在运行时动态部署 Servlet、过滤器、监听器,以及为 Servlet 和过滤器增加 URL 映射等。
1、通过createServlet方法创建Servlet
- T createServlet(Class clazz)
2、通过addServlet动态注册Servlet:
- ServletRegistration.Dynamic addServlet(String servletName, String className)
- ServletRegistration.Dynamic addServlet(String servletName,Class<? extends Servlet> servletClass)
- ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
**3、为Servlet配置映射信息 **
- ServletRegistration getServletRegistration(String servletName)
- Map<string,? extends servletregistration> getServletRegistrations()
以上 ServletContext 新增的方法要么是在 ServletContextListener 的 contexInitialized 方法中调用,要么是在 ServletContainerInitializer 的 onStartup() 方法中调用。
ServletContainerInitializer也是Servlet3.0新增的一个接口,容器在启动时使用 JAR 服务 API(JAR Service API) 来发现 ServletContainerInitializer 的实现类,并且容器将 WEB-INF/lib 目录下 JAR 包中的类都交给该类的 onStartup() 方法处理,我们通常需要在该实现类上使用 @HandlesTypes 注解来指定希望被处理的类,过滤掉不希望给 onStartup() 处理的类。
HttpServletRequest 对文件上传的支持
此前对于文件上传需要依赖三方框架实现。Servlet3.0 提供了优雅的解决方案,在HttpServletRequest提供2个方法用于从请求中解析出上传的文件。
- Part getPart(String name)
- Collection getParts()
1 | Part photo = request.getPart("photo"); |
- 通过@MultipartConfig注解对上传操作做一些配置,大小、保存路径等。
- MIME类型一定是 multipart/form-data,否则会抛出异常。