Servlet3.0的出現(xiàn)是servlet史上最大的變革,其中的許多新特性大大的簡化了web應(yīng)用的開發(fā),為廣大勞苦的程序員減輕了壓力,提高了web開發(fā)的效率。主要新特性有以下幾個:
專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計、做網(wǎng)站、成都外貿(mào)網(wǎng)站建設(shè)公司服務(wù),電腦端+手機端+微信端的三站合一,更高效的管理,為中小企業(yè)金門免費做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了千余家企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴充和轉(zhuǎn)變。
一、注解配置
Servlet3.0新規(guī)范順應(yīng)了時代的潮流,使用注解配置,取代混亂的web.xml全局配置。在這之前我們在創(chuàng)建servlet,filter,listener時,都是在web.xml中配置。
//創(chuàng)建一個servlet需要在web.xml中配置如下內(nèi)容 <servlet> <servlet-name>myFirstServlet</servlet-name> <servlet-class>Test.myServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>myFirstServlet</servlet-name> <url-pattern>/aaa</url-pattern> </servlet-mapping>
//我們只使用一行代碼完成servlet的配置 @WebServlet(name = "myFirstServlet",urlPatterns = {"/aaaa"}) public class myServlet extends HttpServlet { @Override public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher rd = req.getRequestDispatcher("/default.jsp"); rd.forward(req,resp); } }
關(guān)于filter和listener的注解配置方法和上述形式一樣,在3.0新規(guī)范中主要提供了以下一些注解用于配置:
還有一些,暫時沒有涉及,就不列舉了
二、Servlet3.0 Web模塊化開發(fā)
在這之前我們對于web應(yīng)用中的各個Servlet,F(xiàn)ilter,Listener都是需要在web.xml中進行配置,如果只是本項目中的各個點的配置,那倒還好,但是如果我們引入框架,是不是每個框架中的各種配置也是需要在我們的web.xml中配置?這無疑會導(dǎo)致我們唯一的web.xml中內(nèi)容混亂。Servlet3.0新規(guī)范提出了模塊化開發(fā),也就是每個Servlet,F(xiàn)ilter,Listener都可以有屬于自己的配置文件,功能和web.xml一樣,它只負責(zé)配置當前的servlet。然后我們只需要將配置文件和自己寫的Servlet等內(nèi)容打包成jar,引入到具體項目中即可。(就像我們想要使用了某個功能,引入了從網(wǎng)上下載的jar包到項目中)下面我們看如何使用,由于Servlet,F(xiàn)ilter,Listener的配置類似,此處以Servlet為例作為演示:
首先我們寫一個servlet類:
public class MyServlet extends HttpServlet { @Override public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ RequestDispatcher rd = req.getRequestDispatcher("/default.jsp"); rd.forward(req,resp); } }
然后我們創(chuàng)建一個web-fragment.xml文件,這就是屬于此Servlet自己的配置文件,功能類似于Web.xml,只是這個是私有的。鍵入以下內(nèi)容:
<?xml version="1.0" encoding="UTF-8"?> <web-fragment xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd" metadata-complete="false"> <servlet> <servlet-name>myServlet</servlet-name> <servlet-class>Test.MyServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>myServlet</servlet-name> <url-pattern>/index</url-pattern> </servlet-mapping> </web-fragment>
我們可以對比看出,web.xml文件和web-fragment.xml文件除了頭部的不一樣,一個是web-app,一個是web-fragment,別處幾乎一樣。我們創(chuàng)建的這個servlet主要負責(zé)攔截URL為index的請求,并轉(zhuǎn)向default.jsp頁面。
接下來我們看如何打包jar,然后再次為我們項目使用。第一步,無論你是用javac命令還是用IDE編譯,首先我們需要將此.java文件編譯成class文件。在你的電腦的任意位置創(chuàng)建一個空文件夾,將編譯后的class文件及其包復(fù)制進去,因為我們MyServlet在Test包下,此處我就是將Test文件夾復(fù)制進去(你們需要根據(jù)自己建立的文件進行操作)
然后創(chuàng)建一個空文件夾,命名為META-INF,一定要這樣命名,因為等我們把jar包引入到項目中之后,一旦web應(yīng)用啟動時,就會去我們引入的jar包的此文件夾下查找web-fragment.xml文件并加載,如果沒有找到就不會加載,我們的配置也就不會生效。此時我們文件夾中的內(nèi)容如下:
將剛剛寫完的web-fragment.xml文件復(fù)制到META-INF下,然后我們將這兩個文件夾壓縮成zip格式,然后修改zip為jar即可(因為jar和zip的區(qū)別就在于jar中多了一個META-INF文件夾,如果我們已經(jīng)手動添加了,那他們這兩種格式就是一樣了)
此處我們使用手動添加META-INF文件夾,然后壓縮zip格式的形式來完成打包jar的工作,你也可以使用jdk自帶jar命令來完成打包操作,效果是一樣的。然后我們將此jar包復(fù)制到任意web應(yīng)用的WEB-INF/lib下,這就是web應(yīng)用的所有外部引入包所存放的地方。然后我們啟動web容器:
結(jié)果如上,當我們請求index,攔截器攔截并調(diào)向default.jsp頁面。這樣我們就完成了通過引入外部的jar包而不需要做任何配置,使用了其功能。可能此例并沒有很好的展示了這種模塊化開發(fā)的優(yōu)勢,等到我們學(xué)到框架的時候就可以很直觀的感受到這種方式的簡潔,易于攜帶。
三、異步處理
在傳統(tǒng)的servlet開發(fā)中,如果servlet調(diào)用了一個耗時很長的邏輯處理方法,那么此servlet必須待在原地等待方法調(diào)用結(jié)束,這是很低效的一種形式。servlet3.0提出了異步處理的概念,也就是釋放了主程序,大大提高了運行效率。
Servlet3.0中異步處理主要是通過接口AsyncContext來實現(xiàn)的,我們可以通過HttpServletRequest對象來過去該接口的實現(xiàn)對象。
AsyncContext getAsyncContext();
在使用異步處理之前,我們還需要配置指定當前的servlet是支持異步處理。有兩種方法,第一種是在web.xml中配置
<async-supported>true</async-supported>
或者使用webservlet指定屬性asyncSupported=true。下面用一個實例演示如何使用servlet的異步處理機制:
@WebServlet(name = "myservlet",urlPatterns = "/index",asyncSupported = true) public class MyServlet extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ resp.setContentType("text/html;charset=UTF-8"); PrintWriter writer = resp.getWriter(); writer.println("servlet 開始:"+new Date()+"<br />"); writer.flush(); AsyncContext asy = req.startAsync(); asy.setTimeout(4000); asy.start(new MyInfo(asy)); writer.println("servlet 結(jié)束:"+new Date()+"<br />"); writer.flush(); } }
我們可以看到,這個servlet非常簡單,截取URL為index的請求,首先打印啟動時間,然后通過request的startAsync方法創(chuàng)建AsyncContext 對象,設(shè)置過期時間,啟動異步處理。這個線程類代碼如下:
public class MyInfo extends Thread { private AsyncContext asyncContext; public MyInfo(AsyncContext as){ this.asyncContext = as; } @Override public void run(){ try { Thread.sleep(3000); PrintWriter pw = asyncContext.getResponse().getWriter(); pw.println("hello walker:"+new Date()+"<br />"); asyncContext.complete(); } catch (InterruptedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
一個構(gòu)造方法接受AsyncContext 對象,run方法中,先打印一句話然后結(jié)束異步調(diào)用。我們看看結(jié)果:
通過時間我們可以看到servlet開始和結(jié)束幾乎同時,而我們的異步處理卻相差三秒鐘,正是我們sleep的三秒鐘。雖然我們實現(xiàn)了在servlet中異步調(diào)用別的線程來處理一些邏輯,但是我們還是不能完全控制整個異步處理中的各個過程,比如何時開始,何時結(jié)束等。Servlet3.0中的AsyncListener接口提供了以下幾個方法幫助我們監(jiān)控整個過程:
想要實現(xiàn)監(jiān)控異步調(diào)用,首先需要編寫一個類繼承自AsyncListener然后實現(xiàn)如上四個方法,之后這個類就是一個可以監(jiān)控異步調(diào)用的監(jiān)聽器。
public class MyAsyncListener implements AsyncListener { public void onComplete(AsyncEvent var1) throws IOException{ System.out.println("異步調(diào)用結(jié)束了。。。"); } public void onTimeout(AsyncEvent var1) throws IOException{ System.out.println("異步調(diào)用超時了。。。"); } public void onError(AsyncEvent var1) throws IOException{ System.out.println("異步調(diào)用出錯了。。。"); } public void onStartAsync(AsyncEvent var1) throws IOException{ System.out.println("異步調(diào)用開始了。。。"); } }
在我們的Servlet主程序中使用以下語句綁定此異步監(jiān)聽器:
asy.addListener(new MyAsyncListener());
此時異步處理的四個結(jié)點的動態(tài),我們都是實時掌控的。但是需要注意一點的是:雖然理論上我們是可以監(jiān)聽四個狀態(tài)的,但是其實異步開始這個事件我們是沒法監(jiān)聽的,也就是異步開始的方法永遠不會被觸發(fā),原因是在注冊AsyncContext 的時候,已經(jīng)開始了異步,然而我們卻在注冊之后才綁定監(jiān)聽器,自然是不能監(jiān)聽到異步開始這個事件的。
四、文件上傳API
對于傳統(tǒng)的文件上傳,我們是需要借助于外部工具的,例如:common-fileupload等。自從servlet3.0新規(guī)范以來,改進了文件上傳API。
<body> <h2>這是index頁面</h2> <form method="post" action="/submit" enctype="multipart/form-data"> 姓名:<input type="text" name="name" /><br /><br /> 頭像:<input type="file" name="mFile" /><br /><br /> <input type="submit" value="提交" /> </form> </body>
我們知道,在html中上傳文件的表單用type="file"來指定,這是一點,還有一點就是from標簽的enctype屬性,他指定了表單參數(shù)的編碼方式,主要有以下三種:
對于需要上傳文件功能的我們自然選擇第二個參數(shù)值,正如上述代碼展示的一樣。下面我們寫一個servlet用于處理上傳的信息。
@WebServlet(name = "myServlet",urlPatterns = {"/submit"}) @MultipartConfig //處理文件上傳的servlet需要配置此注解 public class FileUpload extends HttpServlet { public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{ resp.setContentType("text/html;charset=UTF-8"); PrintWriter writer = resp.getWriter(); Part part = req.getPart("mFile"); writer.println("文件類型:"+part.getContentType()+"<br />"); writer.println("文件名:"+part.getName()+"<br />"); part.write("C:\\Users\\Administrator\\Desktop\\photo.jpg"); } }
在servlet3.0中采用Part接口來處理文件上傳,可以通過HtppServletRequest的以下兩個方法來獲取此接口對象:
Part getPart(String name); Collection<Part> getParts();
一個part對應(yīng)于我們一個文件上傳域,也就是一個input類型為file的元素。part中有以下一些方法:
String getContentType(); //返回文件類型,如image/png String getName(); //返回文件名 String getSubmittedFileName(); long getSize(); //返回文件的大小 void write(String var1) throws IOException; //將文件寫入到服務(wù)器磁盤 void delete() throws IOException; //刪除此文件 String getHeader(String var1); //獲取指定文件名的值 Collection<String> getHeaders(String var1); //獲取指定文件名的所有的值 Collection<String> getHeaderNames(); //獲取所有Header 的name集合
在上面的程序中,我們使用了其中一些方法。打印了文件類型,文件名,最后將文件保存到本地桌面上。下面是運行的結(jié)果截圖:
綜上就是關(guān)于文件上傳API的基本使用情況,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。
名稱欄目:詳解Servlet3.0新特性(從注解配置到websocket編程)
標題路徑:http://chinadenli.net/article20/pcpjjo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供軟件開發(fā)、做網(wǎng)站、全網(wǎng)營銷推廣、自適應(yīng)網(wǎng)站、網(wǎng)站內(nèi)鏈、響應(yīng)式網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)