Servlet 3.0

[转自:http://blog.csdn.net/xiazdong/article/details/7208316]

Servlet 3.0 新特性概览

 

1.ServletFilterListener无需在web.xml中进行配置,可以通过Annotation进行配置;

2.模块化编程,即将各个Servlet模块化,将配置文件也分开配置。

3.Servlet异步处理,应对复杂业务处理;

4.异步Listener,对于异步处理的创建、完成等进行监听;

5. 文件上传API简化;

 

tomcat 7.0.X 支持Servlet 3.0

 

一、Annotation支持

 

1.Servlet

 

原本Servlet开发完后,必须在web.xml中配置如下代码:

 

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><servlet>      

<![if !supportLists]>2.  <![endif]>    <servlet-name></servlet-name>  

<![if !supportLists]>3.  <![endif]>    <servler-class></servlet-class>  

<![if !supportLists]>4.  <![endif]>    <load-on-startup></load-on-startup>  

<![if !supportLists]>5.  <![endif]>    <init-param>  

<![if !supportLists]>6.  <![endif]>         <param-name></param-name>  

<![if !supportLists]>7.  <![endif]>         <param-value></param-value>  

<![if !supportLists]>8.  <![endif]>    </init-param>  

<![if !supportLists]>9.  <![endif]></servlet>  

<![if !supportLists]>10.<![endif]><servlet-mapping>  

<![if !supportLists]>11.<![endif]>     <servlet-name></servlet-name>  

<![if !supportLists]>12.<![endif]>      <url-pattern></url-pattern>  

<![if !supportLists]>13.<![endif]></servlet-mapping>  

现在只需要在java源文件的Servlet类前面加上:

@WebServlet(name="",urlPatterns={""},initParams={@WebInitParam(name="",value=""),loadOnStartup=1})

public class FirstServlet extends HttpServlet{}

 

代码示例:

实现一个最简单的Servlet

 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>package org.servlet;  

<![if !supportLists]>2.  <![endif]>import java.io.*;  

<![if !supportLists]>3.  <![endif]>import javax.servlet.*;  

<![if !supportLists]>4.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>5.  <![endif]>import javax.servlet.annotation.*;  

<![if !supportLists]>6.  <![endif]>/* 

<![if !supportLists]>7.  <![endif]>       name == <servlet-name> 

<![if !supportLists]>8.  <![endif]>       urlPatterns == <url-pattern>, 

<![if !supportLists]>9.  <![endif]>       loadOnStartup == <load-on-startup> 

<![if !supportLists]>10.<![endif]>       initParam == <init-param> 

<![if !supportLists]>11.<![endif]>       name == <param-name> 

<![if !supportLists]>12.<![endif]>       value == <param-value> 

<![if !supportLists]>13.<![endif]>*/  

<![if !supportLists]>14.<![endif]>@WebServlet(name="HelloServlet" ,urlPatterns={"/HelloServlet"},loadOnStartup=1,  

<![if !supportLists]>15.<![endif]>                    initParams={  

<![if !supportLists]>16.<![endif]>                           @WebInitParam(name="name",value="xiazdong"),  

<![if !supportLists]>17.<![endif]>                           @WebInitParam(name="age",value="20")  

<![if !supportLists]>18.<![endif]>                    })  

<![if !supportLists]>19.<![endif]>public class HelloServlet extends HttpServlet{  

<![if !supportLists]>20.<![endif]>       public void init(ServletConfig config)throws ServletException{  

<![if !supportLists]>21.<![endif]>              super.init(config);  

<![if !supportLists]>22.<![endif]>       }  

<![if !supportLists]>23.<![endif]>       public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{  

<![if !supportLists]>24.<![endif]>              request.setCharacterEncoding("GBK");  

<![if !supportLists]>25.<![endif]>              ServletConfig config = getServletConfig();  

<![if !supportLists]>26.<![endif]>              PrintWriter out = response.getWriter();  

<![if !supportLists]>27.<![endif]>              out.println("<html>");  

<![if !supportLists]>28.<![endif]>              out.println("<body>");  

<![if !supportLists]>29.<![endif]>              out.println("Hello world"+"<br />");  

<![if !supportLists]>30.<![endif]>              out.println(config.getInitParameter("name"));  

<![if !supportLists]>31.<![endif]>              out.println("</body>");  

<![if !supportLists]>32.<![endif]>              out.println("</html>");  

<![if !supportLists]>33.<![endif]>       }  

<![if !supportLists]>34.<![endif]>}  

 

这样的话只需要将class文件放入WEB-INF\classes 中,不需要再web.xml中作任何改动就完成部署;

 

2.Filter

 

原本Filter的配置如下:

 

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><filter>  

<![if !supportLists]>2.  <![endif]>    <filter-name></filter-name>  

<![if !supportLists]>3.  <![endif]>    <filter-class></filter-class>  

<![if !supportLists]>4.  <![endif]><filter>  

<![if !supportLists]>5.  <![endif]><filter-mapping>  

<![if !supportLists]>6.  <![endif]>    <filter-name></filter-name>  

<![if !supportLists]>7.  <![endif]>    <url-pattern></url-pattern>  

<![if !supportLists]>8.  <![endif]></filter-mapping>   

<![if !supportLists]>9.  <![endif]>  

<![if !supportLists]>10.<![endif]>   

现在只需要在java源文件的Filter类前面加上

@WebFilter(filterName="",urlPattern={"/"});

 

3.Listener

 

原本在web.xml中配置如下:

 

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><listener>   

<![if !supportLists]>2.  <![endif]>      <listener-class></listener-class>  

<![if !supportLists]>3.  <![endif]></listener>  

<![if !supportLists]>4.  <![endif]>  

<![if !supportLists]>5.  <![endif]>   

现在只需要在java源文件的Listener类前面加上@WebListener即可;

 

二、web模块化

 

原本一个web应用的任何配置都需要在web.xml中进行,因此会使得web.xml变得很混乱,而且灵活性差,因此Servlet 3.0可以将每个ServletFilterListener打成jar包,然后放在WEB-INF\lib中;注意各自的模块都有各自的配置文件,这个配置文件的名称为  web-fragment.xml ;

 

制作一个Servlet模块的步骤:

1.编写Servlet,并编译;

2.将此编译class文件及所在包通过jar包命令打成jar包;

3.将此jar包用winrar打开,并将其中的META-INF中的manifest删除并添加 web-fragment.xml

4.将此jar包放入WEB-INF\lib中即可;

 

web-fragment.xml注意点:

1.根元素为<web-fragment>;

2.<name></name>表示模块名称;

3.<ordering></ordering>是此模块的加载顺序;

4.<before><others/></before>表示第一个加载;

5.<after><name>A</name></after>表示比A后面加载;

6.可以在里面部署listenerfilterservlet

当然可以不设置任何的模块加载顺序;

 

代码示例:

配置两个listener模块;

FirstListener.java

 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>   

<![if !supportLists]>2.  <![endif]>  

<![if !supportLists]>3.  <![endif]>package org.listener;  

<![if !supportLists]>4.  <![endif]>import javax.servlet.annotation.*;  

<![if !supportLists]>5.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>6.  <![endif]>import javax.servlet.*;  

<![if !supportLists]>7.  <![endif]>import java.util.*;  

<![if !supportLists]>8.  <![endif]>import java.sql.*;  

<![if !supportLists]>9.  <![endif]>import javax.naming.*;  

<![if !supportLists]>10.<![endif]>public class FirstListener implements ServletRequestListener{  

<![if !supportLists]>11.<![endif]>       public void requestInitialized(ServletRequestEvent event){  

<![if !supportLists]>12.<![endif]>              System.out.println("FirstListener created");  

<![if !supportLists]>13.<![endif]>       }  

<![if !supportLists]>14.<![endif]>       public void requestDestroyed(ServletRequestEvent event){  

<![if !supportLists]>15.<![endif]>              System.out.println("FirstListener destroyed");  

<![if !supportLists]>16.<![endif]>       }  

<![if !supportLists]>17.<![endif]>}  

FirstListener web-fragment.xml内容:

 

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><?xml version="1.0" encoding="ISO-8859-1"?>  

<![if !supportLists]>2.  <![endif]><web-fragment xmlns="http://java.sun.com/xml/ns/javaee"  

<![if !supportLists]>3.  <![endif]>  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

<![if !supportLists]>4.  <![endif]>  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  

<![if !supportLists]>5.  <![endif]>                      <A href="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"">http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  

<![if !supportLists]>6.  <![endif]> version="3.0">    

<![if !supportLists]>7.  <![endif]>       <name>FirstListener</name>  

<![if !supportLists]>8.  <![endif]>       <listener>  

<![if !supportLists]>9.  <![endif]>              <listener-class>org.listener.FirstListener</listener-class>  

<![if !supportLists]>10.<![endif]>       </listener>  

<![if !supportLists]>11.<![endif]>       <ordering>  

<![if !supportLists]>12.<![endif]>              <before>  

<![if !supportLists]>13.<![endif]>                    <others/>  

<![if !supportLists]>14.<![endif]>              </before>  

<![if !supportLists]>15.<![endif]>       </ordering>  

<![if !supportLists]>16.<![endif]></web-fragment>  


SecondListener.java 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>package org.listener;  

<![if !supportLists]>2.  <![endif]>import javax.servlet.annotation.*;  

<![if !supportLists]>3.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>4.  <![endif]>import javax.servlet.*;  

<![if !supportLists]>5.  <![endif]>import java.util.*;  

<![if !supportLists]>6.  <![endif]>import java.sql.*;  

<![if !supportLists]>7.  <![endif]>import javax.naming.*;  

<![if !supportLists]>8.  <![endif]>public class SecondListener implements ServletRequestListener{  

<![if !supportLists]>9.  <![endif]>       public void requestInitialized(ServletRequestEvent event){  

<![if !supportLists]>10.<![endif]>             System.out.println("SecondListener created");  

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>       }  

<![if !supportLists]>2.  <![endif]>       public void requestDestroyed(ServletRequestEvent event){  

<![if !supportLists]>3.  <![endif]>             System.out.println("SecondListener destroyed");  

<![if !supportLists]>4.  <![endif]>       }  

<![if !supportLists]>5.  <![endif]>}  

SecondListener web-fragment.xml内容是:

 

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><?xml version="1.0" encoding="ISO-8859-1"?>  

<![if !supportLists]>2.  <![endif]><web-fragment xmlns="http://java.sun.com/xml/ns/javaee"  

<![if !supportLists]>3.  <![endif]>  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

<![if !supportLists]>4.  <![endif]>  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  

<![if !supportLists]>5.  <![endif]>                      <A href="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"">http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"  

<![if !supportLists]>6.  <![endif]> version="3.0">    

<![if !supportLists]>7.  <![endif]>       <name>SecondListener</name>  

<![if !supportLists]>8.  <![endif]>       <listener>  

[html] view plaincopy

<![if !supportLists]>1.  <![endif]>       <listener-class>org.listener.SecondListener</listener-class>  

<![if !supportLists]>2.  <![endif]></listener>  

<![if !supportLists]>3.  <![endif]><ordering>  

<![if !supportLists]>4.  <![endif]>      <after>  

<![if !supportLists]>5.  <![endif]>             <name>FirstListener</name>  

<![if !supportLists]>6.  <![endif]>       </after>  

<![if !supportLists]>7.  <![endif]></ordering>  

<![if !supportLists]>8.  <![endif]>b-fragment>  

然后分别打成jar包,放入 WEB-INF\lib中即可;

 

随便访问一个web应用,然后发现 tomcat控制台输出:

看出先加载FirstListener,再加载SecondListener

 

三、Servlet 异步处理

 

ServletMVC中作为控制器,控制器负责分发任务给MODEL完成,然后把结果交给JSP显示;

而如果有许多MODEL,其中有一个MODEL处理时间很长,则会导致整个页面的显示很慢;

异步处理关键点:将复杂业务处理另外开一个线程,而Servlet将执行好的业务先送往jsp输出,等到耗时业务做完后再送往JSP页面;

一句话:先显示一部分,再显示一部分;

异步处理Servlet的注意点是:

1.需要在Annotation中注明 asyncSupported=true;

 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>package org.sync;  

<![if !supportLists]>2.  <![endif]>import javax.servlet.*;  

<![if !supportLists]>3.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>4.  <![endif]>import javax.servlet.annotation.*;  

<![if !supportLists]>5.  <![endif]>import java.io.*;  

<![if !supportLists]>6.  <![endif]>@WebServlet(name="AsyncServlet",urlPatterns={"/AsyncServlet"},asyncSupported=true)  

<![if !supportLists]>7.  <![endif]>public class AsyncServlet extends HttpServlet{  

<![if !supportLists]>8.  <![endif]>       public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{    

<![if !supportLists]>9.  <![endif]>              request.setCharacterEncoding("GBK");  

<![if !supportLists]>10.<![endif]>              response.setContentType("text/html;charset=GBK");  

<![if !supportLists]>11.<![endif]>              PrintWriter out = response.getWriter();  

<![if !supportLists]>12.<![endif]>              out.println("<html>");  

<![if !supportLists]>13.<![endif]>              out.println("<body>");  

<![if !supportLists]>14.<![endif]>              out.println("====页面开始====<hr />");  

<![if !supportLists]>15.<![endif]>              AsyncContext actx = request.startAsync();  

<![if !supportLists]>16.<![endif]>              actx.setTimeout(30*3000);  

<![if !supportLists]>17.<![endif]>              actx.start(new MyThread(actx));  

<![if !supportLists]>18.<![endif]>              out.println("====页面结束====<hr />");  

<![if !supportLists]>19.<![endif]>              out.println("</body>");  

<![if !supportLists]>20.<![endif]>              out.println("</html>");  

<![if !supportLists]>21.<![endif]>              out.flush();  

<![if !supportLists]>22.<![endif]>       }  

<![if !supportLists]>23.<![endif]>}  

<![if !supportLists]>24.<![endif]>class MyThread implements Runnable{  

<![if !supportLists]>25.<![endif]>       private AsyncContext actx;  

<![if !supportLists]>26.<![endif]>       public MyThread(AsyncContext actx){  

<![if !supportLists]>27.<![endif]>              this.actx = actx;  

<![if !supportLists]>28.<![endif]>       }  

<![if !supportLists]>29.<![endif]>       public void run(){  

<![if !supportLists]>30.<![endif]>              try{  

<![if !supportLists]>31.<![endif]>                   Thread.sleep(5*1000); //消耗5  

<![if !supportLists]>32.<![endif]>                    actx.dispatch("/1.jsp");  

<![if !supportLists]>33.<![endif]>              }  

<![if !supportLists]>34.<![endif]>              catch(Exception e){}  

<![if !supportLists]>35.<![endif]>       }  

<![if !supportLists]>36.<![endif]>}  

1.jsp

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><%@ page contentType="text/html;charset=GBK" pageEncoding="GBK" session="false"%>  

<![if !supportLists]>2.  <![endif]><html>  

<![if !supportLists]>3.  <![endif]>       <body>  

<![if !supportLists]>4.  <![endif]>       <%  

<![if !supportLists]>5.  <![endif]>              out.println("======复杂业务方法====");  

<![if !supportLists]>6.  <![endif]>       %>  

<![if !supportLists]>7.  <![endif]>      </body>  

<![if !supportLists]>8.  <![endif]></html>  


四、异步监听器

 

异步监听器用来监听异步处理事件;即中讲到的知识点;

此监听器类似于ServletContextListener的机制;

只需要实现AsyncListener接口即可;

此接口有4个方法:
public void onStartAsync(AsyncEvent event)throws IOException;

public void onComplete(AsyncEvent event);

public void onTimeout(AsyncEvent event);

public void onError(AsyncEvent event);

 

以下是监听器实现的代码:

 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>package org.listener;  

<![if !supportLists]>2.  <![endif]>import javax.servlet.annotation.*;  

<![if !supportLists]>3.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>4.  <![endif]>import javax.servlet.*;  

<![if !supportLists]>5.  <![endif]>import java.util.*;  

<![if !supportLists]>6.  <![endif]>import java.sql.*;  

<![if !supportLists]>7.  <![endif]>import javax.naming.*;  

<![if !supportLists]>8.  <![endif]>import java.io.*;  

<![if !supportLists]>9.  <![endif]>public class MyListener implements AsyncListener{  

<![if !supportLists]>10.<![endif]>       public void onStartAsync(AsyncEvent event)throws IOException{}  

<![if !supportLists]>11.<![endif]>       public void onComplete(AsyncEvent event){  

<![if !supportLists]>12.<![endif]>              System.out.println("-----------------------Complete");  

<![if !supportLists]>13.<![endif]>      }  

<![if !supportLists]>14.<![endif]>       public void onTimeout(AsyncEvent event){  

<![if !supportLists]>15.<![endif]>       }  

<![if !supportLists]>16.<![endif]>       public void onError(AsyncEvent event){}  

<![if !supportLists]>17.<![endif]>}  

 

Servlet异步处理处添加:

actx.addListener(new MyListener());就可以添加监听器,每当异步处理完成时就会触发onComplete()事件,输出Complete

 

五、文件上传改进API

 

原本文件上传时通过 common-fileupload或者SmartUpload,上传比较麻烦,在Servlet 3.0 中不需要导入任何第三方jar包,并且提供了很方便进行文件上传的功能;

 

注意点:

1. html <input type="file">表示文件上传控件;

2. form enctype="multipart/form-data"

3.Servlet类前加上 @MultipartConfig

4.request.getPart()获得;

 

下面是一个文件上传的例子:

upload.html

 

[html] view plaincopy

<![if !supportLists]>1.  <![endif]><html>  

<![if !supportLists]>2.  <![endif]>       <body>  

<![if !supportLists]>3.  <![endif]>              <form method="post" enctype="multipart/form-data" action="upload">  

<![if !supportLists]>4.  <![endif]>             <input type="file" id="file" name="file"/>  

<![if !supportLists]>5.  <![endif]>             <input type="text" id="name" name="name"/>  

<![if !supportLists]>6.  <![endif]>              <input type="submit" value="提交"/>  

<![if !supportLists]>7.  <![endif]>              </form>  

<![if !supportLists]>8.  <![endif]>       </body>  

<![if !supportLists]>9.  <![endif]></html>  


UploadServlet.java

 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>package org.servlet;  

<![if !supportLists]>2.  <![endif]>import java.io.*;  

<![if !supportLists]>3.  <![endif]>import javax.servlet.*;  

<![if !supportLists]>4.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>5.  <![endif]>import javax.servlet.annotation.*;  

<![if !supportLists]>6.  <![endif]>   

<![if !supportLists]>7.  <![endif]>@WebServlet(name="UploadServlet" ,urlPatterns={"/upload"})  

<![if !supportLists]>8.  <![endif]>@MultipartConfig  

<![if !supportLists]>9.  <![endif]>public class UploadServlet extends HttpServlet{  

<![if !supportLists]>10.<![endif]>       public void init(ServletConfig config)throws ServletException{  

<![if !supportLists]>11.<![endif]>              super.init(config);  

<![if !supportLists]>12.<![endif]>       }  

<![if !supportLists]>13.<![endif]>       public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{  

<![if !supportLists]>14.<![endif]>              Part part = request.getPart("file");  

<![if !supportLists]>15.<![endif]>              PrintWriter out = response.getWriter();  

<![if !supportLists]>16.<![endif]>              out.println("此文件的大小:"+part.getSize()+"<br />");  

<![if !supportLists]>17.<![endif]>              out.println("此文件类型:"+part.getContentType()+"<br />");  

<![if !supportLists]>18.<![endif]>              out.println("文本框内容:"+request.getParameter("name")+"<br />");  

<![if !supportLists]>19.<![endif]>              out.println(UploadUtil.getFileName(part)+"<br />");  

<![if !supportLists]>20.<![endif]>              part.write("F:\\1."+UploadUtil.getFileType(part));  

<![if !supportLists]>21.<![endif]>       }  

<![if !supportLists]>22.<![endif]>}  

UploadUtil.java

由于在Servlet 3.0中很难获取上传文件的类型,因此我写了两个工具类,可以方便开发;

 

[java] view plaincopy

<![if !supportLists]>1.  <![endif]>/** 

<![if !supportLists]>2.  <![endif]> * 此工具类只适用于Servlet 3.0 

<![if !supportLists]>3.  <![endif]> * 为了弥补 Servlet 3.0 文件上传时获取文件类型的困难问题 

<![if !supportLists]>4.  <![endif]> *  

<![if !supportLists]>5.  <![endif]> * @author xiazdong 

<![if !supportLists]>6.  <![endif]> */  

<![if !supportLists]>7.  <![endif]>import javax.servlet.http.*;  

<![if !supportLists]>8.  <![endif]>public class UploadUtil{  

<![if !supportLists]>9.  <![endif]>       public static String getFileType(Part p){  

<![if !supportLists]>10.<![endif]>              String name = p.getHeader("content-disposition");  

<![if !supportLists]>11.<![endif]>              String fileNameTmp = name.substring(name.indexOf("filename=")+10);  

<![if !supportLists]>12.<![endif]>              String type = fileNameTmp.substring(fileNameTmp.indexOf(".")+1,fileNameTmp.indexOf("\""));  

<![if !supportLists]>13.<![endif]>              return type;  

<![if !supportLists]>14.<![endif]>       }  

<![if !supportLists]>15.<![endif]>       public static String getFileName(Part p){  

<![if !supportLists]>16.<![endif]>              String name = p.getHeader("content-disposition");  

<![if !supportLists]>17.<![endif]>              String fileNameTmp = name.substring(name.indexOf("filename=")+10);  

<![if !supportLists]>18.<![endif]>              String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf("\""));  

<![if !supportLists]>19.<![endif]>              return fileName;  

<![if !supportLists]>20.<![endif]>       }  

<![if !supportLists]>21.<![endif]>}  

<![if !supportLists]>22.<![endif]>  

<![if !supportLists]>23.<![endif]>   

<![if !supportLists]>24.<![endif]>   

 

 

 

posted on 2013-11-02 17:51  ONLY LOVE PROGRAME  阅读(399)  评论(0编辑  收藏  举报

导航