[轉自:http://blog.csdn.net/xiazdong/article/details/7208316]html
Servlet 3.0 新特性概覽java
1.Servlet、Filter、Listener無需在web.xml中進行配置,能夠經過Annotation進行配置;web
2.模塊化編程,即將各個Servlet模塊化,將配置文件也分開配置。sql
3.Servlet異步處理,應對複雜業務處理;編程
4.異步Listener,對於異步處理的建立、完成等進行監聽;tomcat
5. 文件上傳API簡化;session
tomcat 7.0.X 支持Servlet 3.0app
本來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中做任何改動就完成部署;
本來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={"/"});
本來在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.xml中進行,所以會使得web.xml變得很混亂,並且靈活性差,所以Servlet 3.0能夠將每一個Servlet、Filter、Listener打成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.能夠在裏面部署listener、filter、servlet
固然能夠不設置任何的模塊加載順序;
代碼示例:
配置兩個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在MVC中做爲控制器,控制器負責分發任務給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;
本來文件上傳時經過 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]>