Servlet3.0新功能详解版权声明

原创
小哥 3年前 (2022-11-11) 阅读数 7 #大杂烩

Servlet 3.0 新功能概述

Servlet 3.0 作为 Java EE 6 规范体系成员,以及 Java EE 6 规格一起发布。此版本是以前的版本(Servlet 2.5)提供了许多新功能以简化 Web 应用程序的开发和部署。其中几个特性的引入对开发人员来说非常令人兴奋 Java 来自社区的赞美之声:

  1. 异步处理支持:通过此功能,Servlet 线程不再需要一直阻塞,直到处理业务以输出响应,并最终结束 Servlet 线在接收到请求之后,Servlet 一个线程可以将耗时的操作委托给另一个线程来完成,将自己返回容器而不生成响应。对于业务处理耗时的情况,这将大大减少服务器资源的使用,并提高并发处理的速度。
  2. 新的注释支持:为了简化,此版本中添加了几个注释 Servlet,筛选器(Filter)和听众(Listener)声明 web.xml 此版本不再需要部署配置文件。
  3. 可插拔支持:熟悉 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 和筛选器不会启用异步处理功能,如果您想按如下方式使用该功能,则必须启用该功能:

  1. 用于使用传统部署配置文件。 (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 >

  2. 对于使用 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 接口表示。它可以监视以下四个事件:

  1. 当异步线程启动时,调用 AsyncListener 的 onStartAsync(AsyncEvent event) 方法;
  2. 当异步线程出错时,调用 AsyncListener 的 onError(AsyncEvent event) 方法;
  3. 如果异步线程执行超时,则调用 AsyncListener 的 onTimeout(AsyncEvent event) 方法;
  4. 异步执行完成后,调用 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 顶部标签 有一个 metadata-complete 属性,该属性指定当前部署描述文件是否是完全的。如果设置为 true,容器在部署时将仅依赖于部署配置文件,忽略所有注释(并跳过) web-fragment.xml 扫描,即禁用插件支持,请参阅以下关于 可插补性支持 如果未配置或设置属性。 false,则表示启用注解支持(和可插补性支持)。

@WebServlet

@WebServlet 用于声明类。 Servlet,容器将在部署时处理注释,容器将部署相应的类 Servlet注释具有下表中给出的一些常见属性(以下所有属性都是可选的, vlaue 或者 urlPatterns 这通常是必要的,两者不能共存,如果同时指定,通常会被忽略。 value 值):

表 1. @WebServlet 主要属性列表

属性名

类型

描述

name

String

指定 Servlet 的 name 属性,相当于 如果没有明确指定, Servlet 的值是类的完全限定名。

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 中的相应配置 元素,容器在部署时根据指定的属性发布类。 Servlet.其等效物 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 中 子标签。@WebInitParam 下表给出了一些常见属性:

表 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 中的相应配置 元素,容器在部署时根据指定的属性发布类。过滤器。它等价的 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 中配置 标签它是等效的 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 >

如上所示, 标签的值通常由其他 web-fragment.xml 定义顺序时参考文件,该顺序通常不在当前文件中使用,它用作当前文件的标识。

在标签内,我们可以定义当前 web-fragment.xml 文件与其他文件之间的相对位置关系 子标签已实现。在这两个子标签中可以传递。 标签以指定相应的文件。例如:

1

2

3

4

< after >

< name >FragmentB</ name >

< name >FragmentC</ name >

</ after >

上述片段意味着当前文件必须在中。 FragmentB 和 FragmentC 解析后。 其用法相同,这意味着当前文件必须更早。 标签中列出 web-fragment.xml 文件。

除了通过比较文档之外。 除了中列出的那些,Servlet 还提供了简化的标签。 。它表示除当前文件之外的所有文件。 web-fragment.xml 文件标签的优先级低于使用的标签。 明确指定的相对位置关系。

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) 中使用 标记为现有 Servlet 增加映射信息。

以上 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 在中,您可以真正感受到这些新功能带来的实质性变化。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除