Servlet3.0新特性:这些你都知道么??
共 14040字,需浏览 29分钟
·
2021-03-14 16:37
从今天开始,我们进入 springboot 系列了。
本文是 springboot 系列第 1 篇,平常我们用 springboot 最多的场景是开发 web 项目,而 springboot 中开发 web 用的是 springmvc,而 springmvc 是依靠 servlet 建立起来的,所以我们需要先了解 servlet,servlet 比较早的版本是 2.5,然后 3.0 改动比较大,目前已经 5.0 以上的版本了,3.0 改动比较大,所以本文主要以 servlet3.0 为例,来说一下 servlet3.0 中的一些新特性。
1、依赖软件及版本
jdk1.8 maven3.6.1 tomcat10
2、Servlet3.0 新特性
新增注解支持,通过注解的方式可以非常方便的定义 servlet、filter、listener Servlet3.0 简化文件上传(@MultipartConfig) Servlet3.0 对异步处理支持 Servlet3.0 对组件可插拔的支持(web-fragment.xml) Servlet3.0 对三大组件(servlet、filter、listener)动态注册的支持
下面我们一个个来看下。
2、通过注解定义三大组件
servlet3.0 之前,定义 servlet、filter、listener,都需在 web.xml 中进行配置,而 3.0 及后面的版本中 web.xml 不是必须的了,可有可无,可以采用注解的方式来定义这些组件。
Servlet 3.0 的部署描述文件 web.xml 的顶层标签有一个 metadata-complete 属性,如下图,该属性指定当前的部署描述文件是否是完全的,如果设置为 true,就是说整个 web 的配置信息都在 web.xml 中指定,则容器在部署时将只依赖 web.xml 文件,忽略所有的注解(同时也会跳过 web-fragment.xml 的扫描,亦即禁用可插性支持,具体请看后文关于可插性支持可插性支持) 的讲解);如果不配置该属性,或者将其设置为 false,则表示启用注解支持(和可插性支持)。
下面来看下如何通过注解的方式定义三大组件。
3、@WebServlet:定义 servlet
@WebServlet 主要属性列表
属性名 | 类型 | 描述 |
---|---|---|
name | String | 指定 Servlet 的 name 属性,如果没有显式指定,则该 Servlet 的取值即为类的全限定名。 |
value | String[] | 该属性等价于 urlPatterns 属性,value 和 urlPatterns 两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组 Servlet 的 URL 匹配模式 |
loadOnStartup | int | 指定 Servlet 的加载顺序 |
initParams | WebInitParam[] | 指定一组 Servlet 初始化参数 |
asyncSupported | boolean | 声明 Servlet 是否支持异步操作模式,默认是 false,后面会在 servlet 异步处理的部分讲解 |
description | String | 该 Servlet 的描述信息 |
displayName | String | 该 Servlet 的显示名,通常配合工具使用 |
用法
(1)、自定义一个类,需继承jakarta.servlet.http.HttpServlet
(2)、重写service
方法
(3)、类上添加@WebServlet
注解来定义 servlet 的配置信息,如下,大家重点看下@WebServlet 注解的几个属性,基本上和 web.xml 中定义 Servlet 参数是一致的。
@WebServlet(
name = "myServlet", // servlet 名称
urlPatterns = "/myServlet", // 哪些请求会被这个servlet处理
// value 参数同 urlPatterns,二者选其一
loadOnStartup = 1, // 设置servlet加载属性,当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载;正数的值越小,启动该servlet的优先级越高。
initParams = {
@WebInitParam(name = "param1", value = "value1"),
@WebInitParam(name = "param2", value = "value2")
}, // 定义servlet初始化参数
asyncSupported = false // 是否支持异步
)
案例
创建一个 maven 项目,添加 servlet5.0 依赖
<dependency>
<groupId>jakarta.servletgroupId>
<artifactId>jakarta.servlet-apiartifactId>
<version>5.0.0-M1version>
<scope>providedscope>
dependency>
创建 servlet,代码如下,MyServlet 会处理/mySevlet 请求,servlet 接受到请求之后,会将当前 servlet 的初始化参数输出到客户端。
package com.javacode2018.springboot.lesson001.demo1;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
@WebServlet(
name = "myServlet", // servlet 名称
urlPatterns = "/myServlet", // 哪些请求会被这个servlet处理
// value 参数同 urlPatterns,二者选其一
loadOnStartup = 1, // 设置servlet加载属性,当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载;正数的值越小,启动该servlet的优先级越高。
initParams = {
@WebInitParam(name = "param1", value = "value1"),
@WebInitParam(name = "param2", value = "value2")
}, // 定义servlet初始化参数
asyncSupported = false // 是否支持异步
)
public class MyServlet extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Enumeration initParameterNames = this.getInitParameterNames();
while (initParameterNames.hasMoreElements()) {
String initParamName = initParameterNames.nextElement();
String initParamValue = this.getInitParameter(initParamName);
try {
resp.getWriter().append(String.format("%s:%s
", initParamName, initParamValue));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
运行程序,通常我们会将 web 项目部署到 tomcat 中,tomcat 目前已经到 10 了,每个版本支持的 servlet 不一样,对应关系如下表
tomcat版本和servlet版本对应关系:https://tomcat.apache.org/whichversion.html
Servlet Spec | JSP Spec | EL Spec | WebSocket Spec | Authentication (JASIC) Spec | Apache Tomcat Version | Latest Released Version | Supported Java Versions |
---|---|---|---|---|---|---|---|
5.0 | 3.0 | 4.0 | 2.0 | 2.0 | 10.0.x | 10.0.2 | 8 and later |
4.0 | 2.3 | 3.0 | 1.1 | 1.1 | 9.0.x | 9.0.43 | 8 and later |
3.1 | 2.3 | 3.0 | 1.1 | 1.1 | 8.5.x | 8.5.63 | 7 and later |
3.1 | 2.3 | 3.0 | 1.1 | N/A | 8.0.x (superseded) | 8.0.53 (superseded) | 7 and later |
3.0 | 2.2 | 2.2 | 1.1 | N/A | 7.0.x | 7.0.108 | 6 and later (7 and later for WebSocket) |
2.5 | 2.1 | 2.1 | N/A | N/A | 6.0.x (archived) | 6.0.53 (archived) | 5 and later |
2.4 | 2.0 | N/A | N/A | N/A | 5.5.x (archived) | 5.5.36 (archived) | 1.4 and later |
2.3 | 1.2 | N/A | N/A | N/A | 4.1.x (archived) | 4.1.40 (archived) | 1.3 and later |
2.2 | 1.1 | N/A | N/A | N/A | 3.3.x (archived) | 3.3.2 (archived) | 1.1 and later |
这里我们使用最新的 tomcat10,下载地址
https://tomcat.apache.org/download-10.cgi
将案例发布到 tomcat 运行,然后访问地址http://localhost:8080/myServlet
即可访问我们上面定义的 servlet,输出如下图
4、@WebFilter:定义 Filter
@WebFilter 的常用属性
属性名 | 类型 | 描述 |
---|---|---|
filterName | String | 指定过滤器的 name 属性 |
value | String[] | 该属性等价于 urlPatterns 属性,value 和 urlPatterns 两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组过滤器的 URL 匹配模式 |
servletNames | String[] | 指定过滤器将应用于哪些 Servlet,取值是 @WebServlet 中的 name 属性的取值,或者是 web.xml 中 的取值。 |
dispatcherTypes | DispatcherType | 指定过滤器的转发模式,具体取值包括:ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。 |
initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于 标签。 |
asyncSupported | boolean | 声明过滤器是否支持异步操作模式 |
description | String | 该过滤器的描述信息 |
displayName | String | 该过滤器的显示名,通常配合工具使用 |
dispatcherTypes 参数有 4 个值
值 | 说明 |
---|---|
REQUEST | 默认值,通过前端发送过来的请求会被拦截 |
FOWARD | 通过 forward 转发过来的请求会被拦截 |
INCLUDE | 通过 include 过来的请求会被拦截 |
ERROR | 这个可能开发者不是很熟悉,意思是当触发了一次 error 的时候,就会走一次指定的过滤器 |
ASYNC | 会拦截异步的请求,这个以后会在讲 servlet 异步的时候会说。 |
用法详解
(1)、自定义一个类,需继承jakarta.servlet.http.HttpFilter
(2)、重写doFilter
方法,注意是 protected 的 doFilter 方法,如下
@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
super.doFilter(req, res, chain);
}
(3)、类上添加@WebFilter
注解来定义 Filter 的配置信息,如下,大家重点看下@WebFilter 的几个属性,基本上和 web.xml 中定义 Filter 参数是一致的
@WebFilter(
filterName = "myFilter", // filter名称
urlPatterns = "/*", //拦截的地址
servletNames = "myServlet", //拦截的servlet名称列表
dispatcherTypes = {DispatcherType.REQUEST},//拦截的请求类型
initParams = {@WebInitParam(name = "p1", value = "v1")}, //定义Filter初始化参数列表
asyncSupported = false // 是否支持异步
)
案例
package com.javacode2018.springboot.lesson001.demo1;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.http.HttpFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(
filterName = "myFilter", // filter名称
urlPatterns = "/*", //拦截的地址
servletNames = "myServlet", //拦截的servlet名称列表
dispatcherTypes = {DispatcherType.REQUEST},//拦截的请求类型
initParams = {@WebInitParam(name = "p1", value = "v1")}, //定义Filter初始化参数列表
asyncSupported = false // 是否支持异步
)
public class MyFilter extends HttpFilter {
@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
System.out.println(req.getRequestURL()); // 输出请求的地址
super.doFilter(req, res, chain);
}
}
**Filter 会拦截哪些请求呢?**urlPatterns、servletNames、dispatcherTypes 都匹配的请求才会被拦截
案例发布到 tomcat,浏览器中访问http://localhost:8080/myServlet
,控制台输出
5、@WebListener:定义监听器
@WebListener 的常用属性
属性名 | 类型 | 是否可选 | 描述 |
---|---|---|---|
value | String | 是 | 该监听器的描述信息。 |
用法
(1)、自定义一个类,实现下面任意一个监听器接口
监听器类 | 说明 |
---|---|
ServletContextListener | 监听 servlet 上下文的创建和销毁,web 容器启动和销毁的时候会被调用 |
ServletContextAttributeListener | 监听 ServletContext 中属性变化 |
HttpSessionListener | 监听 session 的创建和销毁 |
HttpSessionActivationListener | Activate 与 Passivate 是用于置换对象的动作,当 session 对象为了资源利用或负载平衡等原因而必须暂时储存至硬盘或其它储存器时(透 过对象序列化),所作的动作称之为 Passivate,而硬盘或储存器上的 session 对象重新加载 JVM 时所采的动作称之为 Activate,所以容 易理解的,sessionDidActivate()与 sessionWillPassivate()分别于 Activeate 后与将 Passivate 前呼叫。 |
HttpSessionAttributeListener | session 中添加值或者移除值的时候会被调用 |
HttpSessionBindingListener | 实现了 HttpSessionBindingListener 的类,在和 session 绑定、解除绑定时触发其事件 |
ServletRequestListener | 监听 request 的创建和销毁 |
ServletRequestAttributeListener | requet 中添加值和删除值的时候会被调用 |
(2)类上添加@WebListener 注解
@WebListener("自定义的ServletContextListener")
案例
下面我们自定义一个 ServletContextListener,用来监听容器的启动和销毁,代码如下
package com.javacode2018.springboot.lesson001.demo1;
import jakarta.servlet.ServletContextEvent;
import jakarta.servlet.ServletContextListener;
import jakarta.servlet.annotation.WebListener;
/**
* 通过 @WebListener 注解定义监听器
*/
@WebListener("自定义的ServletContextListener")
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println(this.getClass().getName() + ",监听servlet容器的启动!!!!!");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println(this.getClass().getName() + ",监听servlet容器的销毁!!!!!");
}
}
启动 tomcat,然后再停止 tomcat,控制台输出
下一篇继续介绍 servlet3.0 的其他部分。
接下来介绍 2 个功能,比较适合小白
使用 idea 如何创建 web 项目
如何在 idea 中配置 tomcat
下面我们来看看。
6、使用 idea 创建 web 项目
step1、先安装 maven
如果对 maven 不熟悉的可以先去看我的maven系列,springboot 系列每篇中都会用到 maven。
这里我们使用 maven3.6.1,请大家也安装这个版本,环境咱们保持一致,这样运行的过程中,才能确保结果是一致,避免走一些不必要的弯路。
maven3.6.1 下载地址:
https://archive.apache.org/dist/maven/maven-3/3.6.1/binaries/apache-maven-3.6.1-bin.tar.gz
maven 版本列表地址:
https://archive.apache.org/dist/maven/maven-3/
step2、idea 中配置 maven
File->Settings->Maven
step3:创建 web 项目
File->New->Project->Maven,勾选Create from archetype
,选择maven-archetype-webapp
,如下,这样一个 web 项目就创建好了。
7、idea 中配置 tomcat
step1、下载 tomcat
这里我们下载 tomcat10,下载地址,大家根据自己的机器选择需要下载的包,我的机器是 window 64 位的,所以下载的是 64-bit windows.zip
https://tomcat.apache.org/download-10.cgi
step2、解压下载的 tomcat 包
解压之后,tomcat 目录结构如下,大家复制这个目录的地址,这就是 tomcat 的 home 目录地址,稍后在 idea 中配置的时候需要用到
step3、idea 中配置 tomcat
我们把案例中的项目发布到 tomcat
step4、将 tomcat 添加到 server 列表中
需要先在 view 中找到 services,点击之后打开 services 列表窗口,然后在列表窗口中将 tomcat 添加到 services 列表中,具体操作过程如下:
8、源码
https://gitee.com/javacode2018/springboot-series