Servlet3.0新特性
主要内容
知识点1: 非阻塞 知识点2: 注解 知识点3: 文件上传
一.非阻塞
示例
我们编写一个PrintServlet,在一个死循环中打印输出:
out.println(Thread.currentThread().getName()+": Hello,我是PrintServlet,马上要进入死循环打印了!"); out.close(); while(true){ System.out.println("正在打印,请稍后......"); }
在之前版本的Servlet中,访问该Servlet后,再次访问就不再有响应,因为当前线程阻塞,在处理死循环 。
http://localhost:8080/servlet_demo/PrintServlet.do 请求PrintServlet,在后台死循环打印。 http://localhost:8080/servlet_demo/PrintServlet.do 请求PrintServlet,处于阻塞状态,一直在加载状态。
Servlet3.0版本,增加了非阻塞特性:
接收请求后,启动一个异步线程处理请求,客户端可以继续请求这个Servlet,而不必等待上一次请求返回;
默认情况下,Servlet3.0版本Servlet并没有这个特性,需要在web.xml中进行配置:
<servlet> <servlet-name>PrintServlet</servlet-name> <servlet-class>servlet.PrintServlet.do</servlet-class> <async-supported>true</async-supported> </servlet> ? http://localhost:8080/servlet_demo/PrintServlet.do 请求PrintServlet,处于非阻塞状态,依然可以响应
二.注解
Servlet3.0中可以使用注解(annotation)替代web.xml进行配置;
通常用的注解有五种类型:
@WebServlet:对Servlet进行配置 @WebInitParam:配置Servlet初始化参数 @WebFilter:配置过滤器 @WebListener :配置监听器 @MultipartConfig:对文件上传的支持
1.@WebServlet注解
对Servlet进行配置示例,包括的属性如下,这些属性除了vlaue或urlPatterns是必选的,其他的都是可选的: 1)name:等价于web.xml配置文件中的 <servlet-name>。如果没有指定, Servlet 的<servlet-name>取值为类的全限定名,比如XXX.XXX.XXX。 2)urlPatterns:等价于web.xml配置文件中的 <url-pattern> 标签 3)value:等价于 urlPatterns 属性。 4)loadOnStartup:等价于web.xml配置文件中的<load-on-startup> 标签 5)initParams :等价于web.xml配置文件中的<init-param> 标签,他的参数是@WebInitParam注解的集合(此注解之后介绍) 6)asyncSupported:等价于web.xml配置文件中的<async-supported> 标签 7)description:等价于web.xml配置文件中的<description> 标签 8)displayName:等价于web.xml配置文件中的 <display-name> 标签 ?
示例
@WebServlet(urlPatterns = {"/demo"}, asyncSupported = true, loadOnStartup = -1, name = "DemoServlet", displayName = "chinasofti", initParams = { @WebInitParam(name = "username", value = "etc") } ) 该注解同下面xml配置相同 <servlet> <display-name> DemoServlet </display-name> <servlet-name>servlet.DemoServlet</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>etc</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name> DemoServlet </servlet-name> <url-pattern>/demo</url-pattern> </servlet-mapping> ?
2.@WebInitParam注解
@WebInitParam:配置Servlet初始化参数,常用属性有三个,这三个属性当中只有description为可选属性: name:等价于web.xml配置文件中的 <param-name> value :等价于web.xml配置文件中的<param-value> description:等价于web.xml配置文件中的<description> ?
示例
initParams = { @WebInitParam(name = "username", value = "qianfeng") } 同下面xml文件配置 <init-param> <param-name>username</param-name> <param-value>qianfeng</param-value> </init-param> ?
3.@WebFilter注解
@WebFilter:配置过滤器此注解为声明一个过滤器,主要属性有以下几个。 在这些属性当中value、urlPatterns、servletNames 三个属性至少要包含其中的一个,并且 value 和 urlPatterns 属性只能有一个,如果两个同时配置,一般情况下value取值将会被忽略。其他的都是可选属性。 filterName:等价于web.xml配置文件中的 <filter-name>标签 value:该属性等价于 urlPatterns 属性 urlPatterns:等价于web.xml配置文件中的 <url-pattern> 标签 servletNames:指定该过滤器将应用的 范围。如果是注解的话取值是 @WebServlet 中的 name 属性的取值,如果servlet这 web.xml 中配置的话,取值是 <servlet-name> 的取值 dispatcherTypes:过滤器的转发模式。取值包括: ASYNC(异步)、ERROR(错误)、FORWARD(请求转发)、INCLUDE(包含)、REQUEST(请求)。 initParams:等价于web.xml配置文件中的<init-param> 标签 asyncSupported:等价于web.xml配置文件中的<async-supported> 标签 description:等价于web.xml配置文件中的<description> 标签 displayName:等价于web.xml配置文件中的<display-name> 标签 ?
示例
@WebFilter(servletNames = {"LoginServlet"},filterName="LoginFilter") public class LoginFilter implements Filter{ ........ 同下面xml配置 <filter> <filter-name> LoginFilter </filter-name> <filter-class>filter.LoginFilter </filter-class> </filter> <filter-mapping> <filter-name> LoginFilter </filter-name> <servlet-name> LoginServlet </servlet-name> </filter-mapping> ?
4.WebListener 注解
@WebListener:配置监听器,此注解是用来声明监听器,它主要的属性只有一个: value:这个属性表示的是监听器的描述信息,整个配置可以简写成@WebListener("XXX")
示例
@WebListener("this is a listener") public class CounterListener implements ServletContextListener{ …… 同下面xml文件配置 <listener> <listener-class>listener.CounterListener</listener-class> </listener> ?
三.文件上传
Servlet3.0以前版本没有对文件上传进行支持,只能用第三方组件实现;
Servlet3.0中对文件上传进行了支持,核心接口是Part接口,该接口中的核心方法如下:
方法声明方法描述void delete()删除part对象对应文件项的基本存储,包括删除任何相关的临时磁盘文件String getContentType()请求上传文件的类型String getHeader(String name):获取上传文件内容的指定名字的请求头信息Collection<String> getHeaderNames()获取上传文件请求的全部请求头名称,返回的是一个包含请求头名称的集合Collection<String> getHeaders(String name)通过请求头名称,获取全部对应的请求信息,返回的是一个集合InputStream getInputStream()获取输入流String getName()获取控件的名字Long getSize()获取上传文件的大小void write(String fileName)将文件写入到物理磁盘
在Servlet3.0版本中,请求接口提供了获取Part实例的方法;
方法声明方法描述Part getPart(String name)根据上传控件名称获取上传文件对应的Part对象Collection<Part> getParts()获取所有上传文件对应的Part对象。
示例
upload.jsp: ? <form action="uploadServelt" method="post" enctype="multipart/form-data“ > 文件1:<input type="file" name="myfile1"/><br/> 文件2:<input type="file" name="myfile2"/><br/> <input type="submit" name="submit" value="upload"/> </form> ?
定义UploadServlet,实现上传功能;注解内容如下:
@WebServlet("/uploadServelt") @MultipartConfig( location = "E:\\upload",//文件存放路径 maxFileSize = 8388608,//最大上传文件大小 fileSizeThreshold = 819200,//当数据量大于该值时,内容将被写入文件。 maxRequestSize = -1 //针对该 multipart/form-data 请求最大数量,默认值为 -1,表示没有限制。以字节为单位。 ) ?
定义UploadServlet,实现上传功能;核心代码如下 :
//获取所有上传文件对应的Part对象 Collection<Part> parts = request.getParts(); //遍历上传文件对应的part对象,将文件写入上传文件目录 for (Iterator<Part> iterator = parts.iterator(); iterator.hasNext();) { Part part = iterator.next(); //获取content-disposition请求头,提取文件名称 String cotentDisposition = part.getHeader("content-disposition"); System.out.println("cotent-disposition="+cotentDisposition); String fileName = null; //使用正则表达是部分匹配,获取上传文件名称 Pattern pattern = Pattern.compile("filename=\".+\""); Matcher matcher = pattern.matcher(cotentDisposition); if(matcher.find()){ fileName = matcher.group(); System.out.println("fileName="+fileName); fileName = fileName.substring(10, fileName.length()-1); System.out.println("subFileName="+fileName); } if(fileName!=null){ part.write(fileName); } ?
定义过滤器,解决文件名统一编码问题;核心代码如下 :
public void init(FilterConfig filterConfig) throws ServletException { //初始化 glEncoding = filterConfig.getInitParameter("encoding"); } ? public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { if (glEncoding != null) { // request编码 request.setCharacterEncoding(glEncoding); // response编码 response.setContentType("text/html;charset=" + glEncoding); } // 传给下一个过滤器 chain.doFilter(request, response); } ?
四.常见问题
Servlet3.0的非阻塞特性是什么意思?如何实现? Servlet3.0中有哪几个常用的注解类型? Servlet3.0对文件上传进行了哪些支持?
五.总结
Servlet3.0中增加了非阻塞特性支持,可以在web.xml中或者使用注解进行配置,使得Servlet可以异步处理请求; Servlet3.0可以使用注解替代web.xml的部分内容,常用的注解类型有@WebServlet、@WebFilter、@WebListener、@WebInitParam。 Servlet3.0中对文件上传进行了支持,提供了Part接口以及@MultipartConfig注解,可以方便地实现文件上传;