Servlet3.0新特性
Servlet3.0新特性
制作人:全心全意
新增注释
新增注释是Servlet3.0中的重大革新之一。通过使用注释就无须再web.xml文件中对Servlet或者过滤器进行配置。Servlet3.0新增的注释有@WebServlet、@WebFilter、@WebListener和@WebInitParam等。
-
@WebServlet
@WebServlet注释定义在Servlet的类声明之前,用于定义Servlet组件。使用该注释,就无须再web.xml文件中对Servlet进行配置。@WebServlet注释包含很多属性,如下表所示。
属 性 名 | 类 型 | 描 述 |
name | String | 指定Servlet的name属性,等价于<servlet-name>。如果没有显式指定,则该Servlet的取值即为类的全限定名 |
value | String[] | 该属性等价于urlPattern属性,两个属性不能同时使用 |
urlPatterns | String[] | 指定一组Servlet的URL匹配模式。等价于<url-pattern>标签 |
loadOnStartup | int |
指定Servlet的加载顺序,等价于<load-on-startup>标签 |
initParams | WebInitParam[] | 指定一组Servlet初始化参数,等价于<init-pararn>标签 |
asyncSupported | boolean | 声明Servlet是否支持异步操作模式,等价于<async-supported>标签 |
description | String | 该Servlet的描述信息,等价于<description>标签 |
displayName | String | 该Servlet的显示名,通常配合工具使用,等价于<display-name>标签 |
Servlet创建对比示例:
@WebServlet(name = "SServlet", urlPatterns = "/SServlet") public class SServlet extends HttpServlet { //省略Servlet中的代码 }
等价于web.xml中如下配置:
<servlet> <servlet-name>SServlet</servlet-name> <servlet-class>com.SServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>SServlet</servlet-name> <url-pattern>/SServlet</url-pattern> </servlet-mapping>
- @WebFilter
@webFilter注释用于声明过滤器,该注解将会在部署时被容器处理,容器根据具体的属性配置将相应的类部署为过滤器。该属性也包含很多属性,如下表所示。
属 性 名 | 类 型 | 描 述 |
filtername | String | 指定过滤器的name属性,等价于<filter-name> |
value | String[] | 该属性等价于urlPatterns属性。但是两者不应该同时使用 |
urlPatterns | String[] | 指定一组过滤器URL匹配模式。等价于<url-pattern> |
servletNames | String[] | 指定过滤器将应用于哪些Servlet。是@WebServlet中的name属性的取值,或者是web.xml中<servlet-name>的取值 |
initParams | WebInitParam[] | 指定一组过滤器初始化参数,等价于<init-param>标签 |
asyncSupported | Boolean | 声明过滤器是否支持异步操作模式,等价于<async-supported>标签 |
description | String | 该过滤器的描述信息,等价于<description>标签 |
displayName | String | 该过滤器的显示名,通常配合工具使用,等价于<display-name>标签 |
dispatcherTypes | DispatcherType | 指定过滤器的转发模式。具体取值包括ASYNC、ERROR、FORWARD、INCLUDE和REQUEST |
过滤器创建对比示例:
public class Ma { @WebFilter(filterName="char",urlPatterns="/*") public class CharFilter implements Filter{ //省略过滤器中的代码 } }
等价于web.xml中如下配置:
<filter> <filter-name>char</filter-name> <filter-class>com.Ma</filter-class> </filter> <filter-mapping> <filter-name>char</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- @WebListener
该注释用于声明监听器,还可以用于充当给定Web应用上下文中各种Web应用事件的监听器的类。可以使用@WebListener来标注一个实现ServletContextListener、ServletContextAttributeListener、ServletRequestListener、ServletRequestAttributeListener、HttpSessionListener和HttpSessionAttributeListener的类。@WebListener注释有一个value的属性,该属性为可选属性,用于描述监听器信息。
声明监听器示例:
@WebListener("This is only a demo listener") public class Ma { public class CharFilter implements ServletContextListener { //省略监听器中的代码 } }
- @WebInitParam
该注释等价于web.xml文件中的<servlet>和<filter>的<init-param>子标签,该注释通常不单独使用,而是配合@WebServlet或者@WebFilter使用。它的作用是为Servlet或者过滤器指定初始化参数。@WebInitParam注释包含了一些常用属性,如下表所示。
属 性 名 | 类 型 | 是 否 可 选 | 描 述 |
name | String | 否 | 指定参数的名字,等价于<param-name> |
value | String | 否 | 指定参数的值,等价于<param-value> |
description | String | 是 | 关于参数的描述,等价于<description> |
初始化参数对比示例:
@WebServlet(urlPatterns = "/simple", name = "SimpleServlet", initParams = { @WebInitParam(name = "username", value = "zhangsan") }) public class SimpleServlet extends HttpServlet { //省略了Servlet中的代码 }
等价于web.xml中如下配置:
<servlet> <servlet-name>SimpleServlet</servlet-name> <servlet-class>com.SimpleServlet</servlet-class> <init-param> <param-name>username</param-name> <param-value>zhangsan</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>SimpleServlet</servlet-name> <url-pattern>/simple</url-pattern> </servlet-mapping>
文件上传
在Servlet3.0出现之前,处理文件上传是一件非常麻烦的事情,因为要借助第三方组件,例如commons fileupload等。而Servlet3.0出现以后就摆脱了这一问题。使用Servlet3.0可以十分方便地实现文件的上传。实现文件上传需要以下两项内容:
需要添加@MultipartConfig注释
从request对象中获取Part文件对象
@MultipartConfig注释需要标注在@WebServlet注释之上。其具有的属性如下表所示。
属 性 名 | 类 型 | 是 否 可 选 | 描 述 |
fileSizeThreshold | Int | 是 | 当数据量大于该值时,内容将被写入文件 |
location | String | 是 | 存放生成的文件地址 |
maxFileSize | Long | 是 | 允许上传的文件最大值,默认值为-1,表示没有限制 |
maxRequestSize | Long | 是 | 针对该multipart/form-data请求的最大数量,默认值为-1,表示没有限制 |
除了要配置@MultipartConfig注解之外,还需要两个重要的方法,即getPart()与getParts()方法。下面对这两个方法进行详细介绍。
Part getPart(String name)
Collection<Part> getParts()
getPart()方法的name参数表示请求的name文件。getParts()方法可获取请求中的所有文件。上传文件用javax.servlet.http.Part对象来表示。Part接口提供了处理文件的简易方法,如write()、delete()等 。
文件上传实例:
UploadServlet类:Servlet类,实现文件上传
package com.mingrisoft; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import java.io.PrintWriter; import javax.servlet.annotation.MultipartConfig; import org.apache.catalina.core.ApplicationPart; @WebServlet("/UploadServlet") @MultipartConfig() public class UploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); String path = this.getServletContext().getRealPath("/"); //获取服务器地址 Part p = request.getPart("file1"); //获取用户选择的上传文件 if (p.getContentType().contains("image")) { // 仅处理上传的图像文件 ApplicationPart ap = (ApplicationPart) p; String fname1 = ap.getName(); //获取上传文件名 System.out.println(fname1); int path_idx = fname1.lastIndexOf(":") + 1; //对上传文件名进行截取 String fname2 = fname1.substring(path_idx, fname1.length()); p.write(path + "/upload/" + fname2); // 写入 web 项目根路径下的upload文件夹中 System.out.println(path + "/upload/" + fname2); out.write("文件上传成功"); } else{ out.write("请选择图片文件!!!"); } } }
index.jsp页面:放置提交图片文件的文件选择器
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="UploadServlet" enctype="multipart/form-data" method ="post" > 选择文件<input type="file" name="file1" id= "file1"/> <input type="submit" name="upload" value="上传" /> </form> </body> </html>
异步处理
异步处理是Servlet3.0最重要的内容之一。在此之前,一个Servlet的工作流程是:首先,Servlet接收到请求后,需要对请求携带的数据进行一些预处理。接着调用业务接口的某些方法,以完成业务处理。最后,根据处理的结果提交响应,至此,Servlet线程结束。在此过程中,如果任何一个任务没有结束,Servlet线程就处于阻塞状态,知道业务方法执行完毕。对于较大的应用,很容易造成程序性能的降低。
Servlet3.0针对这一问题做了突破性的工作,现在通过使用Servlet3.0的异步处理机制可以将之前的Servlet处理流程调整为以下过程。首先,Servlet接收到请求之后,可能需要对请求携带的数据进行一些预处理;接着Servlet线程将请求转交给一个异步线程来执行业务处理,线程本身返回至容器,此时Servlet还没有生成响应数据,异步线程处理完业务之后,可以直接生成响应数据,或者将请求继续转发给其他Servlet。这样,Servlet线程不再是一直处于阻塞状态以等待业务逻辑的处理,而是启动异步之后可以立即返回。
异步处理机制可以应用于Servlet和过滤器两种组件,由于异步处理的工作模式与普通工作模式有着本质的区别,在默认情况下,并没有开启异步处理特性,如果希望使用该特性,则必须按如下的方法启用:
@WebServlet和@WebFilter注释提供了asyncSupported属性,默认该属性的取值为false,要启用异步处理支持,只需将该属性设置为true即可。
以@WebFilter为例,其配置方法如下所示。
@WebFilter(urlPatterns = "/chFilter", asyncSupported = true) public class DemoFilter implements Filter { //省略过滤器中的代码 }
等价于web.xml中如下配置:
<servlet> <servlet-name>CharServlet</servlet-name> <servlet-class>com.DemoFilter</servlet-class> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>CharServlet</servlet-name> <url-pattern>/chFilter</url-pattern> </servlet-mapping>