Servlet3.0新功能详解版权声明
原创Servlet 3.0 新功能概述
Servlet 3.0 作为 Java EE 6 规范体系成员,以及 Java EE 6 规格一起发布。此版本是以前的版本(Servlet 2.5)提供了许多新功能以简化 Web 应用程序的开发和部署。其中几个特性的引入对开发人员来说非常令人兴奋 Java 来自社区的赞美之声:
- 异步处理支持:通过此功能,Servlet 线程不再需要一直阻塞,直到处理业务以输出响应,并最终结束 Servlet 线在接收到请求之后,Servlet 一个线程可以将耗时的操作委托给另一个线程来完成,将自己返回容器而不生成响应。对于业务处理耗时的情况,这将大大减少服务器资源的使用,并提高并发处理的速度。
- 新的注释支持:为了简化,此版本中添加了几个注释 Servlet,筛选器(Filter)和听众(Listener)声明 web.xml 此版本不再需要部署配置文件。
- 可插拔支持:熟悉 Struts2 开发人员肯定会通过包含的插件进行开发。 Spring 各种通用框架的集成特性仍然记忆犹新。封装相应的插件 JAR 打包并放置在类路径下,Struts2 这些插件可以在运行时自动加载。现在 Servlet 3.0 提供了类似的特性,开发人员可以通过插件轻松扩展现有特性。 Web 应用程序的功能,而不修改原始应用程序。
在下面,我们将逐一解释这些新特性。通过以下研究,读者将能够清楚地理解它们。 Servlet 3.0 改变,并可以成功地将其用于日常开发工作。
异步处理支持
Servlet 3.0 以前,一个普通人 Servlet 主要工作流程,Servlet 收到请求后,您可能需要对请求所携带的数据进行一些预处理,Servlet 螺纹末端。业务处理的第二步通常是最耗时的,这主要体现在数据库操作以及该过程中的其他跨网络调用中,Servlet 在执行业务方法之前,线程处于阻塞状态。在处理业务的过程中,Servlet 资源已被占用而未被释放,这可能会对具有大并发性的应用程序造成性能瓶颈。过去,私人解决方案通常用于提前结束。 Servlet 线程,并及时释放资源。
Servlet 3.0 关于这个问题,已经进行了讨论,现在使用 Servlet 3.0 对于异步处理支持 Servlet 处理流程可以调整为:首先,Servlet 收到请求后,您可能首先需要对请求所携带的数据进行一些预处理,Servlet 线程将请求转发给异步线程以执行业务处理,线程本身返回容器。 Servlet 尚未生成响应数据。异步线程处理业务后,可以直接生成响应数据(异步线程具有 ServletRequest 和 ServletResponse 对象),或继续将请求转发给另一个 Servlet以这种方式, Servlet 线程不再总是处于阻塞状态以等待业务逻辑的处理,而是可以在启动异步线程后立即返回。
可以应用异步处理特性 Servlet 由于异步处理工作模式和正常工作模式在实现上的本质差异,Servlet 和筛选器不会启用异步处理功能,如果您想按如下方式使用该功能,则必须启用该功能:
-
用于使用传统部署配置文件。 (web.xml) 配置 Servlet 以及过滤器外壳,Servlet 3.0 为
和 标签已添加 子标签,该标签的默认值为 false要启用异步处理支持,请设置它。 true 即可。以 Servlet 例如,配置如下: 1
2
3
4
5
<servlet><servlet-name>DemoServlet</servlet-name><servlet-class>footmark.servlet.Demo Servlet</servlet-class><async-supported>true</async-supported></servlet> -
对于使用 Servlet 3.0 提供的 @WebServlet 和 @WebFilter 进行 Servlet 或过滤器配置,两个注释都提供 asyncSupported 属性,默认值为。 false,要启用异步处理支持,只需设置属性 true 即可。以 @WebFilter 例如,配置如下:
1
2
@WebFilter(urlPatterns = "/demo",asyncSupported = true)
public class DemoFilter implements Filter{...}
异步处理的简单模拟。 Servlet 示例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@WebServlet(urlPatterns = "/demo", asyncSupported = true)
public class AsyncDemoServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
out.println("进入Servlet的时间:" + new Date() + ".");
out.flush();
//业务调用在子线程中执行,响应由其输出,主线程退出。
AsyncContext ctx = req.startAsync();
new Thread(new Executor(ctx)).start();
out.println("结束Servlet的时间:" + new Date() + ".");
out.flush();
}
}
public class Executor implements Runnable {
private AsyncContext ctx = null;
public Executor(AsyncContext ctx){
this.ctx = ctx;
}
public void run(){
try {
//等待10秒钟以模拟业务方法的执行。
Thread.sleep(10000);
PrintWriter out = ctx.getResponse().getWriter();
out.println("业务处理时间:" + new Date() + ".");
out.flush();
ctx.complete();
} catch (Exception e) {
e.printStackTrace();
}
}
}
此外Servlet 3.0 还为异步处理提供了侦听器,使用 AsyncListener 接口表示。它可以监视以下四个事件:
- 当异步线程启动时,调用 AsyncListener 的 onStartAsync(AsyncEvent event) 方法;
- 当异步线程出错时,调用 AsyncListener 的 onError(AsyncEvent event) 方法;
- 如果异步线程执行超时,则调用 AsyncListener 的 onTimeout(AsyncEvent event) 方法;
- 异步执行完成后,调用 AsyncListener 的 onComplete(AsyncEvent event) 方法;
注册 AsyncListener,把准备好的 AsyncListener 对象传递给 AsyncContext 对象的 addListener() 方法如下:
1
2
3
4
5
6
7
AsyncContext ctx = req.startAsync();
ctx.addListener(new AsyncListener() {
public void onComplete(AsyncEvent asyncEvent) throws IOException {
// 做一些清洁工作或其他
}
...
});
新注释支持
Servlet 3.0 部署描述文件 web.xml 顶部标签
@WebServlet
@WebServlet 用于声明类。 Servlet,容器将在部署时处理注释,容器将部署相应的类 Servlet注释具有下表中给出的一些常见属性(以下所有属性都是可选的, vlaue 或者 urlPatterns 这通常是必要的,两者不能共存,如果同时指定,通常会被忽略。 value 值):
表 1. @WebServlet 主要属性列表
属性名
类型
描述
name
String
指定 Servlet 的 name 属性,相当于
value
String[]
该属性是等效的 urlPatterns 属性两个属性不能同时使用。
urlPatterns
String[]
指定一组 Servlet 的 URL 匹配模式。相等的
loadOnStartup
int
指定 Servlet 装载顺序的等效值
initParams
WebInitParam[]
指定一组 Servlet 初始化参数,等效
asyncSupported
boolean
声明 Servlet 是否支持异步操作模式,等效
description
String
该 Servlet 描述信息的等效
displayName
String
该 Servlet 通常与工具一起使用的显示名称相当于
下面是一个简单的例子:
1
2
3
4
5
@WebServlet(urlPatterns = {"/simple"}, asyncSupported = true,
loadOnStartup = -1, name = "SimpleServlet", displayName = "ss",
initParams = {@WebInitParam(name = "username", value = "tom")}
)
public class SimpleServlet extends HttpServlet{ … }
完成此配置后,您将无法拥有。 web.xml 中的相应配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< servlet >
< display-name >ss</ display-name >
< servlet-name >SimpleServlet</ servlet-name >
< servlet-class >footmark.servlet.SimpleServlet</ servlet-class >
< load-on-startup >-1</ load-on-startup >
< async-supported >true</ async-supported >
< init-param >
< param-name >username</ param-name >
< param-value >tom</ param-value >
</ init-param >
</ servlet >
< servlet-mapping >
< servlet-name >SimpleServlet</ servlet-name >
< url-pattern >/simple</ url-pattern >
</ servlet-mapping >
@WebInitParam
此注释通常不单独使用,而是结合使用 @WebServlet 或者 @WebFilter 使用其功能是 Servlet 或者过滤器指定初始化参数,该参数等效 web.xml 中
表 2. @WebInitParam 通用属性
属性名
类型
是否可选
描述
name
String
否
指定参数的名称,等效
value
String
否
指定参数的值,等效值
description
String
是
参数的描述是等效的。
@WebFilter
@WebFilter 用于声明类。过滤器,容器将在部署时处理注释,容器将部署相应的类过滤器。该注解具有下表给出的一些常用属性 ( 以下所有属性都是可选的, value、urlPatterns、servletNames 三个必须至少包含一个,并且 value 和 urlPatterns 不能共存,如果同时指定,通常会忽略 value 的取值 ):
表 3. @WebFilter 通用属性
属性名
类型
描述
filterName
String
指定过滤器 name 属性,相当于
value
String[]
该属性是等效的 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
该过滤器通常与工具一起使用的显示名称相当于
下面是一个简单的例子:
1
2
@WebFilter(servletNames = {"SimpleServlet"},filterName="SimpleFilter")
public class LessThanSixFilter implements Filter{...}
完成此配置后,您将无法拥有。 web.xml 中的相应配置
1
2
3
4
5
6
7
8
< filter >
< filter-name >SimpleFilter</ filter-name >
< filter-class >xxx</ filter-class >
</ filter >
< filter-mapping >
< filter-name >SimpleFilter</ filter-name >
< servlet-name >SimpleServlet</ servlet-name >
</ filter-mapping >
@WebListener
此注释用于将类声明为侦听器 @WebListener 标记的类必须至少实现以下接口之一:
- ServletContextListener
- ServletContextAttributeListener
- ServletRequestListener
- ServletRequestAttributeListener
- HttpSessionListener
- HttpSessionAttributeListener
注释使用起来非常简单,具有以下属性:
表 4. @WebListener 通用属性
属性名
类型
是否可选
描述
value
String
是
侦听器的描述。
一个简单的例子如下:
1
2
@WebListener("This is only a demo listener")
public class SimpleListener implements ServletContextListener{...}
这样,就没有必要了 web.xml 中配置
1
2
3
< listener >
< listener-class >footmark.servlet.SimpleListener</ listener-class >
</ listener >
@MultipartConfig
此注释主要用于帮助 Servlet 3.0 中 HttpServletRequest 支持上传文件。注释在中标记 Servlet 以上说明 Servlet 您希望处理的请求。 MIME 类型是 multipart/form-data此外,它还提供了几个属性来简化上传文件的处理。具体如下:
表 5. @MultipartConfig 通用属性
属性名
类型
是否可选
描述
fileSizeThreshold
int
是
当数据量大于此值时,内容将写入文件。
location
String
是
存储生成的文件地址。
maxFileSize
long
是
允许上载的最大文件数。默认值为 -1,表示没有限制。
maxRequestSize
long
是
针对该 multipart/form-data 具有默认值的最大请求数 -1,表示没有限制。
可插补性支持
如果说 3.0 版本新注释支持是为了简化 Servlet/ 过滤器 / 听众的声明 web.xml 对于可选配置, 然后是新的互极性 (pluggability) 支持则将 Servlet 配置的灵活性已提高到一个新的水平。熟悉的 Struts2 开发商知道,Struts2 提供的插件形式包括。 Spring 在各种开发框架的支持下,开发人员甚至可以自己这样做。 Struts2 开发插件,同时 Servlet 的可插补性支持正是基于这样的理念而产生的。使用该特性,现在我们可以在不修改已有 Web 在应用程序的前提下,您只需要以特定格式键入它。 JAR 包放到 WEB-INF/lib 目录中,您可以扩展新功能,而无需额外配置。
Servlet 3.0 介绍了所谓的“Web 模块部署描述符片段“ web-fragment.xml 部署配置文件,必须存储在 JAR 文件的 META-INF 目录中,部署概要文件可以包含可以在 web.xml 中定义的内容。JAR 包裹通常放置在 WEB-INF/lib 目录下,此外所有该模块使用的资源,包括 class 文件、配置文件等只需要由容器的类加载器链在路径上加载,例如 classes 目录等。
现在,为了 Web 应用程序添加了 Servlet 有三种配置方式 ( 过滤器、侦听器和 Servlet 三者的配置是等效的,所以在这里。 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<? xml version = "1.0" encoding = "UTF-8" ?>
< web-fragment
xmlns = http ://java.sun.com/xml/ns/javaee
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" version = "3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
metadata-complete = "true" >
< servlet >
< servlet-name >fragment</ servlet-name >
< servlet-class >footmark.servlet.FragmentServlet</ servlet-class >
</ servlet >
< servlet-mapping >
< servlet-name >fragment</ servlet-name >
< url-pattern >/fragment</ url-pattern >
</ servlet-mapping >
</ web-fragment >
从上面的例子可以看出,web-fragment.xml 与 web.xml 除了标题中的声明。 XSD 参考不同,其主要配置与 web.xml 是相同的。
由于一个 Web 应用程序中可以出现多个。 web-fragment.xml 声明文件,加上 web.xml 文件,加载顺序问题成为必须面对的问题。Servlet 本规范的专家组在其设计中考虑了这一问题,并确定了装载顺序的规则。
web-fragment.xml 包含了两个可选顶部标签,
1
2
3
4
5
6
7
8
9
10
11
12
13
< web-fragment... >
< name >FragmentA</ name >
< ordering >
< after >
< name >FragmentB</ name >
< name >FragmentC</ name >
</ after >
< before >
< others />
</ before >
</ ordering >
...
</ web-fragment >
如上所示,
在
1
2
3
4
< after >
< name >FragmentB</ name >
< name >FragmentC</ name >
</ after >
上述片段意味着当前文件必须在中。 FragmentB 和 FragmentC 解析后。
除了通过比较文档之外。
ServletContext 性能增强
除了上述新特征之外,ServletContext 新版本还增强了对象的功能。该对象现在支持运行时的动态部署。 Servlet、筛选器、侦听器和。 Servlet 和过滤器增加 URL 映射等至 Servlet 例如,过滤器类似于监听器。ServletContext 对于动态配置 Servlet 添加了以下方法:
ServletRegistration.Dynamic addServlet(String servletName,Class<? extends Servlet> servletClass)ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)ServletRegistration.Dynamic addServlet(String servletName, String className)-
T createServlet(Class clazz) - ServletRegistration getServletRegistration(String servletName)
- Map<String,? extends ServletRegistration> getServletRegistrations()
前三种方法具有相同的效果,除了不同的参数类型; createServlet() 方法已创建。 Servlet,通常需要进行一些自定义配置,然后使用。 addServlet() 方法将其动态注册为可使用的服务。 Servlet。两个 getServletRegistration() 该方法主要用于动态 Servlet 增加映射信息,相当于 web.xml( 抑或 web-fragment.xml) 中使用
以上 ServletContext 新方法要么在中。 ServletContextListener 的 contexInitialized 方法,在中。 ServletContainerInitializer 的 onStartup() 方法被调用。
ServletContainerInitializer 也是 Servlet 3.0 容器在启动时使用的新接口。 JAR 服务 API(JAR Service API) 来发现 ServletContainerInitializer 实现类的,容器将 WEB-INF/lib 目录下 JAR 包中的类被赋予该类。 onStartup() 方法处理,我们通常需要在该实现类上使用。 @HandlesTypes 注释指定要处理的类,过滤掉不想给出的类。 onStartup() 类已处理。
HttpServletRequest 支持文件上传
此前,处理上传文件的操作一直是开发人员头疼的问题,因为 Servlet 这本身没有直接支持,需要使用第三方框架来实现,而且使用起来不够简单。现在都是历史了,Servlet 3.0 该功能已经提供,使用非常简单。为此,HttpServletRequest 提供了两种方法来解析来自请求的上传文件:
- Part getPart(String name)
- Collection
getParts()
前者用于在请求中获得给定值。 name 后者用于获取所有文件。每个文件使用一个 javax.servlet.http.Part 要表示的对象。该界面提供了一种处理文件的简单方法,例如 write()、delete() 迄今为止,合并 HttpServletRequest 和 Part 保存上传的文件非常简单,如下所示:
1
2
3
Part photo = request.getPart("photo");
photo.write("/tmp/photo.jpg");
// 可以减少两行代码 request.getPart("photo").write("/tmp/photo.jpg") 一行。
此外,开发人员可以使用上述 @MultipartConfig 自定义上载操作的注释,例如限制上载文件的大小和保存文件的路径。它的用法非常简单,所以我在这里不再重复。
重要的是要注意,如果需要。 MIME 类型不是 multipart/form-data,您不能使用以上两种方法,否则将引发异常。
总结
Servlet 3.0 的许多新功能 Servlet 开发变得更加简单,尤其是异步处理特性和可插补性支持的出现,必将对现有的 MVC 框架具有深远的影响。虽然我们通常不会自己使用 Servlet 编写控制层代码,但可能在下一个版本中。 Struts 在中,您可以真正感受到这些新功能带来的实质性变化。
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123



