zoukankan      html  css  js  c++  java
  • [转]Servlet 3.0 新特性详解

    原文地址:http://blog.csdn.net/xiazdong/article/details/7208316

    Servlet 3.0 新特性概览

     

    1.Servlet、Filter、Listener无需在web.xml中进行配置,可以通过Annotation进行配置;

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

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

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

    5. 文件上传API简化;

     

    tomcat 7.0.X 支持Servlet 3.0

     

    一、Annotation支持

     

    1.Servlet

     

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

     

    1. <servlet>      
    2.     <servlet-name></servlet-name>  
    3.     <servler-class></servlet-class>  
    4.     <load-on-startup></load-on-startup>  
    5.     <init-param>  
    6.          <param-name></param-name>  
    7.          <param-value></param-value>  
    8.     </init-param>  
    9. </servlet>  
    10. <servlet-mapping>  
    11.      <servlet-name></servlet-name>  
    12.       <url-pattern></url-pattern>  
    13. </servlet-mapping>  

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

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

    public class FirstServlet extends HttpServlet{}

     

    代码示例:

    实现一个最简单的Servlet。

     

    1. package org.servlet;  
    2. import java.io.*;  
    3. import javax.servlet.*;  
    4. import javax.servlet.http.*;  
    5. import javax.servlet.annotation.*;  
    6. /* 
    7.        name == <servlet-name> 
    8.        urlPatterns == <url-pattern>, 
    9.        loadOnStartup == <load-on-startup> 
    10.        initParam == <init-param> 
    11.        name == <param-name> 
    12.        value == <param-value> 
    13. */  
    14. @WebServlet(name="HelloServlet" ,urlPatterns={"/HelloServlet"},loadOnStartup=1,  
    15.                     initParams={  
    16.                            @WebInitParam(name="name",value="xiazdong"),  
    17.                            @WebInitParam(name="age",value="20")  
    18.                     })  
    19. public class HelloServlet extends HttpServlet{  
    20.        public void init(ServletConfig config)throws ServletException{  
    21.               super.init(config);  
    22.        }  
    23.        public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{  
    24.               request.setCharacterEncoding("GBK");  
    25.               ServletConfig config = getServletConfig();  
    26.               PrintWriter out = response.getWriter();  
    27.               out.println("<html>");  
    28.               out.println("<body>");  
    29.               out.println("Hello world"+"<br />");  
    30.               out.println(config.getInitParameter("name"));  
    31.               out.println("</body>");  
    32.               out.println("</html>");  
    33.        }  
    34. }  

     

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

     

    2.Filter

     

    原本Filter的配置如下:

     

    1. <filter>  
    2.     <filter-name></filter-name>  
    3.     <filter-class></filter-class>  
    4. <filter>  
    5. <filter-mapping>  
    6.     <filter-name></filter-name>  
    7.     <url-pattern></url-pattern>  
    8. </filter-mapping>   
    9.   
    10.    

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

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

     

    3.Listener

     

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

     

    1. <listener>   
    2.       <listener-class></listener-class>  
    3. </listener>  
    4.   
    5.    

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

     

    二、web模块化

     

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

     

    制作一个Servlet模块的步骤:

    1.编写Servlet,并编译;

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

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

    4.将此jar包放入WEB-INFlib中即可;

     

    web-fragment.xml注意点:

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

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

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

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

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

    6.可以在里面部署listener、filter、servlet

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

     

    代码示例:

    配置两个listener模块;

    FirstListener.java

     

    1.    
    2.   
    3. package org.listener;  
    4. import javax.servlet.annotation.*;  
    5. import javax.servlet.http.*;  
    6. import javax.servlet.*;  
    7. import java.util.*;  
    8. import java.sql.*;  
    9. import javax.naming.*;  
    10. public class FirstListener implements ServletRequestListener{  
    11.        public void requestInitialized(ServletRequestEvent event){  
    12.               System.out.println("FirstListener created");  
    13.        }  
    14.        public void requestDestroyed(ServletRequestEvent event){  
    15.               System.out.println("FirstListener destroyed");  
    16.        }  
    17. }  

    FirstListener 的 web-fragment.xml内容:

     

    1. <?xml version="1.0" encoding="ISO-8859-1"?>  
    2. <web-fragment xmlns="http://java.sun.com/xml/ns/javaee"  
    3.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
    5.                       <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"  
    6.  version="3.0">    
    7.        <name>FirstListener</name>  
    8.        <listener>  
    9.               <listener-class>org.listener.FirstListener</listener-class>  
    10.        </listener>  
    11.        <ordering>  
    12.               <before>  
    13.                     <others/>  
    14.               </before>  
    15.        </ordering>  
    16. </web-fragment>  


    SecondListener.java 

    1. package org.listener;  
    2. import javax.servlet.annotation.*;  
    3. import javax.servlet.http.*;  
    4. import javax.servlet.*;  
    5. import java.util.*;  
    6. import java.sql.*;  
    7. import javax.naming.*;  
    8. public class SecondListener implements ServletRequestListener{  
    9.        public void requestInitialized(ServletRequestEvent event){  
    10.              System.out.println("SecondListener created");  
    1.        }  
    2.        public void requestDestroyed(ServletRequestEvent event){  
    3.              System.out.println("SecondListener destroyed");  
    4.        }  
    5. }  

    SecondListener的 web-fragment.xml内容是:

     

    1. <?xml version="1.0" encoding="ISO-8859-1"?>  
    2. <web-fragment xmlns="http://java.sun.com/xml/ns/javaee"  
    3.   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  
    5.                       <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"  
    6.  version="3.0">    
    7.        <name>SecondListener</name>  
    8.        <listener>  
    1.        <listener-class>org.listener.SecondListener</listener-class>  
    2. </listener>  
    3. <ordering>  
    4.       <after>  
    5.              <name>FirstListener</name>  
    6.        </after>  
    7. </ordering>  
    8. b-fragment>  

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

     

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

    看出先加载FirstListener,再加载SecondListener;

     

    三、Servlet 异步处理

     

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

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

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

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

    异步处理Servlet的注意点是:

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

     

    1. package org.sync;  
    2. import javax.servlet.*;  
    3. import javax.servlet.http.*;  
    4. import javax.servlet.annotation.*;  
    5. import java.io.*;  
    6. @WebServlet(name="AsyncServlet",urlPatterns={"/AsyncServlet"},asyncSupported=true)  
    7. public class AsyncServlet extends HttpServlet{  
    8.        public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{    
    9.               request.setCharacterEncoding("GBK");  
    10.               response.setContentType("text/html;charset=GBK");  
    11.               PrintWriter out = response.getWriter();  
    12.               out.println("<html>");  
    13.               out.println("<body>");  
    14.               out.println("====页面开始====<hr />");  
    15.               AsyncContext actx = request.startAsync();  
    16.               actx.setTimeout(30*3000);  
    17.               actx.start(new MyThread(actx));  
    18.               out.println("====页面结束====<hr />");  
    19.               out.println("</body>");  
    20.               out.println("</html>");  
    21.               out.flush();  
    22.        }  
    23. }  
    24. class MyThread implements Runnable{  
    25.        private AsyncContext actx;  
    26.        public MyThread(AsyncContext actx){  
    27.               this.actx = actx;  
    28.        }  
    29.        public void run(){  
    30.               try{  
    31.                    Thread.sleep(5*1000); //消耗5秒  
    32.                     actx.dispatch("/1.jsp");  
    33.               }  
    34.               catch(Exception e){}  
    35.        }  
    36. }  

    1.jsp

    1. <%@ page contentType="text/html;charset=GBK" pageEncoding="GBK" session="false"%>  
    2. <html>  
    3.        <body>  
    4.        <%  
    5.               out.println("======复杂业务方法====");  
    6.        %>  
    7.       </body>  
    8. </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);

     

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

     

    1. package org.listener;  
    2. import javax.servlet.annotation.*;  
    3. import javax.servlet.http.*;  
    4. import javax.servlet.*;  
    5. import java.util.*;  
    6. import java.sql.*;  
    7. import javax.naming.*;  
    8. import java.io.*;  
    9. public class MyListener implements AsyncListener{  
    10.        public void onStartAsync(AsyncEvent event)throws IOException{}  
    11.        public void onComplete(AsyncEvent event){  
    12.               System.out.println("-----------------------Complete");  
    13.       }  
    14.        public void onTimeout(AsyncEvent event){  
    15.        }  
    16.        public void onError(AsyncEvent event){}  
    17. }  

     

    在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

     

    1. <html>  
    2.        <body>  
    3.               <form method="post" enctype="multipart/form-data" action="upload">  
    4.              <input type="file" id="file" name="file"/>  
    5.              <input type="text" id="name" name="name"/>  
    6.               <input type="submit" value="提交"/>  
    7.               </form>  
    8.        </body>  
    9. </html>  


    UploadServlet.java

     

    1. package org.servlet;  
    2. import java.io.*;  
    3. import javax.servlet.*;  
    4. import javax.servlet.http.*;  
    5. import javax.servlet.annotation.*;  
    6.    
    7. @WebServlet(name="UploadServlet" ,urlPatterns={"/upload"})  
    8. @MultipartConfig  
    9. public class UploadServlet extends HttpServlet{  
    10.        public void init(ServletConfig config)throws ServletException{  
    11.               super.init(config);  
    12.        }  
    13.        public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{  
    14.               Part part = request.getPart("file");  
    15.               PrintWriter out = response.getWriter();  
    16.               out.println("此文件的大小:"+part.getSize()+"<br />");  
    17.               out.println("此文件类型:"+part.getContentType()+"<br />");  
    18.               out.println("文本框内容:"+request.getParameter("name")+"<br />");  
    19.               out.println(UploadUtil.getFileName(part)+"<br />");  
    20.               part.write("F:\1."+UploadUtil.getFileType(part));  
    21.        }  
    22. }  

    UploadUtil.java

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

     

      1. /** 
      2.  * 此工具类只适用于Servlet 3.0 
      3.  * 为了弥补 Servlet 3.0 文件上传时获取文件类型的困难问题 
      4.  *  
      5.  * @author xiazdong 
      6.  */  
      7. import javax.servlet.http.*;  
      8. public class UploadUtil{  
      9.        public static String getFileType(Part p){  
      10.               String name = p.getHeader("content-disposition");  
      11.               String fileNameTmp = name.substring(name.indexOf("filename=")+10);  
      12.               String type = fileNameTmp.substring(fileNameTmp.indexOf(".")+1,fileNameTmp.indexOf("""));  
      13.               return type;  
      14.        }  
      15.        public static String getFileName(Part p){  
      16.               String name = p.getHeader("content-disposition");  
      17.               String fileNameTmp = name.substring(name.indexOf("filename=")+10);  
      18.               String fileName = fileNameTmp.substring(0,fileNameTmp.indexOf("""));  
      19.               return fileName;  
      20.        }  
      21. }  
      22.   
      23.    
      24.   
  • 相关阅读:
    《Programming WPF》翻译 第8章 1.动画基础
    一些被遗忘的设计模式
    《Programming WPF》翻译 第4章 数据绑定
    《Programming WPF》翻译 第3章 控件
    《Programming WPF》翻译 第5章 样式和控件模板
    《Programming WPF》翻译 第7章 绘图
    《Programming WPF》翻译 第9章 自定义控件
    《Programming WPF》翻译 第7章 绘图 (2)
    《Programming WPF》翻译 第8章 前言
    关于Debug和Release之本质区别
  • 原文地址:https://www.cnblogs.com/dirgo/p/5007558.html
Copyright © 2011-2022 走看看