在infoq上有关于servlet3.0的新特性说明,个人觉得比较全面
我们下面就看看其中几个特性:
1.可插拔的Web框架,其实就是web.xml中可以又多个子模块的配置文件组成,而各个子模块的配置文件可以放在各个jar包的META-INFO中,这样就实现web应用的模块化。
类似,可以按照配置的顺序指定了web片段的顺序。通过absolute-ordering进行绝对顺序配置,通过每个fragment的order的after和before标签进行相对顺序配置。
<?xml version="1.0" encoding="GB18030"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"> <absolute-ordering> <name>web-fragment1</name> <name>web-fragment2</name> </absolute-ordering></web-app>
每个fragment1的配置如下:
<?xml version="1.0" encoding="GB18030"?> <web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"> <name>web-fragment1</name> <ordering><after>web-fragment1</after><before><others/></before></ordering> </web-fragment>
2. servlet3.0的annotation支持
对于原来在web.xml定义的servlet,filter,listener,InitParam都可以通过annotation来配置了,而不需要在web.xml中定义。
@WebFilter
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; //asyncSupported=true 对应filter也需要定义asyncSupported=true @WebFilter(urlPatterns={"/*"}, filterName="my3Filter", asyncSupported=true) @WebInitParam(name="a", value="valuea") public class My3Filter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("servlet 3 filter"); arg2.doFilter(arg0, arg1); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("servlet 3 filter init"); } }
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.annotation.WebInitParam; //asyncSupported=true 对应filter也需要定义asyncSupported=true @WebFilter(urlPatterns={"/*"}, filterName="my3Filter", asyncSupported=true) @WebInitParam(name="a", value="valuea") public class My3Filter implements Filter{ @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException { System.out.println("servlet 3 filter"); arg2.doFilter(arg0, arg1); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("servlet 3 filter init"); } }
支持的annotation如下,都可以通过eclipse的提示查到对应的参数配置,
@WebServlet支持的参数有
3. servlet3.0的异步支持
很多时候Servlet要和其他的资源进行互动,例如访问数据库,调用web service。在和这些资源互动的时候,Servlet不得不等待数据返回,然后才能够继续执行。这使得Servlet调用这些资源的时候阻塞。Servlet3.0通过引入异步处理解决了这个问题。异步处理允许线程调用资源的时候不被阻塞,而是直接返回。AsyncContext负责管理从资源来的回应。AsyncContext决定该回应是应该被原来的线程处理还是应该分发给容器中其他的资源。AsyncContext有一些方法如start,dispatch和complete来执行异步处理。
要想使用Servlet3.0的异步处理,我们需要设置@Webservlet和@WebFilter注解的asyncSupport属性。这个属性是布尔值,缺省值是false。
所以,可以在servlet阻塞处理网络,数据库查询等时,可以暂时释放线程资源,处理更多请求,当请求处理完之后重新唤醒线程继续处理原来的请求,达到NIO的效果。
我们看下一个示例
AsyncContext 可以添加监听器作为异步处理过程中状态的跟踪等
import java.io.IOException; import java.util.Date; import javax.servlet.AsyncContext; import javax.servlet.AsyncEvent; import javax.servlet.AsyncListener; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet(asyncSupported=true,name="asyncServlet", urlPatterns="/async") public class AsyncServlet extends HttpServlet{ /** * */ private static final long serialVersionUID = 3903580630389463919L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getWriter().write("hello, async test"); resp.getWriter().println("start:"+new Date()+".<br/>"); resp.getWriter().flush(); final AsyncContext async = req.startAsync(req,resp); async.setTimeout(3000); async.start(new Runnable() { @Override public void run() { ServletRequest request = async.getRequest(); try { Thread.sleep(2000); async.getResponse().getWriter().write("aync thread processing"); async.getResponse().getWriter().flush(); async.getResponse().getWriter().println("async end:"+new Date()+".<br/>"); async.getResponse().getWriter().flush(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); async.addListener(new AsyncListener() { @Override public void onTimeout(AsyncEvent arg0) throws IOException { // TODO Auto-generated method stub } @Override public void onStartAsync(AsyncEvent arg0) throws IOException { // TODO Auto-generated method stub } @Override public void onError(AsyncEvent arg0) throws IOException { // TODO Auto-generated method stub } @Override public void onComplete(AsyncEvent arg0) throws IOException { // TODO Auto-generated method stub } }); resp.getWriter().println("end:"+new Date()+".<br/>"); resp.getWriter().flush(); } }
hello, async teststart?Mon Dec 10 20:23:35 CST 2012. end?Mon Dec 10 20:23:35 CST 2012. aync thread processingasync end?Mon Dec 10 20:23:37 CST 2012.
4.@MultipartConfig 文件上传的支持,以前servlet要处理上传文件一般会使用common file upload组件,现在servlet3.0原生支持了文件上传的处理
location参数指定临时文件存放目录,'
package com.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.MultipartConfig; 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; @WebServlet(asyncSupported=true,name="upload", urlPatterns="/upload") @MultipartConfig(fileSizeThreshold = 10000, maxFileSize = 1000000, maxRequestSize = 1000000, location="E:/logs") public class MultiPartServlet3 extends HttpServlet { /** * */ private static final long serialVersionUID = 7306582588845300635L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Part part = req.getPart("file"); String value = part.getHeader("content-disposition"); System.out.println(value); String filename = value.substring(value.lastIndexOf("=") + 2,value.length() - 1); System.out.println(filename); System.out.println(part.getInputStream().toString()); } }
<form action="upload" method="post" enctype="multipart/form-data"> <input type="file" name="file"><br> <input type="submit" value="submit"> </form>
form-data; name="file"; filename="22.log" 22.log java.io.ByteArrayInputStream@1bdce67
HttpServletRequest To support the multipart/form-data MIME type, the following methods have been added to the HttpServletRequest interface: 为了支持multipart/form-data MIME类型,在HttpServletRequest接口中添加了项目的方法: * Iterable<Part> getParts() * Part getPart(String name) Cookies 为了避免一些跨站点攻击,Servlet3.0支持HttpOnly的cookie。HttpOnly cookie不想客户端暴露script代码。Servlet3.0在Cookie类中添加了如下的方法来支持HttpOnly cookie: * void setHttpOnly(boolean isHttpOnly) * boolean isHttpOnly() ServletContext 通过在ServletContext中添加下面的方法,Servlet3.0允许Servlet或filter被编程的加入到context中: * addServlet(String servletName, String className) * addServlet(String servletName, Servlet servlet) * addServlet(String servletName, Class<? extends Servlet> servletClass) * addFilter(String filterName, String className) * addFilter(String filterName, Filter filter) * addFilter(String filterName, Class<? extends Filter>filterClass) * setInitParameter (String name, String Value)
http://www.ibm.com/developerworks/cn/java/j-lo-servlet30/index.html
http://www.infoq.com/cn/news/2007/06/servlet3