最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Servlet3.0新特性(從注解配置到websocket編程)

 更新時(shí)間:2017年04月25日 10:04:55   作者:Walker_YAM  
Servlet3.0的出現(xiàn)是servlet史上最大的變革,其中的許多新特性大大的簡(jiǎn)化了web應(yīng)用的開(kāi)發(fā),為廣大勞苦的程序員減輕了壓力,提高了web開(kāi)發(fā)的效率。

Servlet3.0的出現(xiàn)是servlet史上最大的變革,其中的許多新特性大大的簡(jiǎn)化了web應(yīng)用的開(kāi)發(fā),為廣大勞苦的程序員減輕了壓力,提高了web開(kāi)發(fā)的效率。主要新特性有以下幾個(gè):

  1. 引入注解配置
  2. 支持web模塊化開(kāi)發(fā)
  3. 程序異步處理
  4. 改進(jìn)文件上傳API
  5. 非阻塞式IO讀取流
  6. Websocket實(shí)時(shí)通信

一、注解配置

Servlet3.0新規(guī)范順應(yīng)了時(shí)代的潮流,使用注解配置,取代混亂的web.xml全局配置。在這之前我們?cè)趧?chuàng)建servlet,filter,listener時(shí),都是在web.xml中配置。

//創(chuàng)建一個(gè)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ī)范中主要提供了以下一些注解用于配置:

  1. Websocket :用于配置socket
  2. WebInitParam :用于配置初始化參數(shù),往往和servlet和filter結(jié)合使用
  3. WebListener :用于配置Listener
  4. WebFilter :用于配置Filter
  5. MultipartConfig :用于文件上傳(后面會(huì)詳細(xì)介紹)

還有一些,暫時(shí)沒(méi)有涉及,就不列舉了

二、Servlet3.0 Web模塊化開(kāi)發(fā)

在這之前我們對(duì)于web應(yīng)用中的各個(gè)Servlet,F(xiàn)ilter,Listener都是需要在web.xml中進(jìn)行配置,如果只是本項(xiàng)目中的各個(gè)點(diǎn)的配置,那倒還好,但是如果我們引入框架,是不是每個(gè)框架中的各種配置也是需要在我們的web.xml中配置?這無(wú)疑會(huì)導(dǎo)致我們唯一的web.xml中內(nèi)容混亂。Servlet3.0新規(guī)范提出了模塊化開(kāi)發(fā),也就是每個(gè)Servlet,F(xiàn)ilter,Listener都可以有屬于自己的配置文件,功能和web.xml一樣,它只負(fù)責(zé)配置當(dāng)前的servlet。然后我們只需要將配置文件和自己寫的Servlet等內(nèi)容打包成jar,引入到具體項(xiàng)目中即可。(就像我們想要使用了某個(gè)功能,引入了從網(wǎng)上下載的jar包到項(xiàng)目中)下面我們看如何使用,由于Servlet,F(xiàn)ilter,Listener的配置類似,此處以Servlet為例作為演示:

首先我們寫一個(gè)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)建一個(gè)web-fragment.xml文件,這就是屬于此Servlet自己的配置文件,功能類似于Web.xml,只是這個(gè)是私有的。鍵入以下內(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>

我們可以對(duì)比看出,web.xml文件和web-fragment.xml文件除了頭部的不一樣,一個(gè)是web-app,一個(gè)是web-fragment,別處幾乎一樣。我們創(chuàng)建的這個(gè)servlet主要負(fù)責(zé)攔截URL為index的請(qǐng)求,并轉(zhuǎn)向default.jsp頁(yè)面。

接下來(lái)我們看如何打包jar,然后再次為我們項(xiàng)目使用。第一步,無(wú)論你是用javac命令還是用IDE編譯,首先我們需要將此.java文件編譯成class文件。在你的電腦的任意位置創(chuàng)建一個(gè)空文件夾,將編譯后的class文件及其包復(fù)制進(jìn)去,因?yàn)槲覀僊yServlet在Test包下,此處我就是將Test文件夾復(fù)制進(jìn)去(你們需要根據(jù)自己建立的文件進(jìn)行操作)

然后創(chuàng)建一個(gè)空文件夾,命名為META-INF,一定要這樣命名,因?yàn)榈任覀儼裫ar包引入到項(xiàng)目中之后,一旦web應(yīng)用啟動(dòng)時(shí),就會(huì)去我們引入的jar包的此文件夾下查找web-fragment.xml文件并加載,如果沒(méi)有找到就不會(huì)加載,我們的配置也就不會(huì)生效。此時(shí)我們文件夾中的內(nèi)容如下:

將剛剛寫完的web-fragment.xml文件復(fù)制到META-INF下,然后我們將這兩個(gè)文件夾壓縮成zip格式,然后修改zip為jar即可(因?yàn)閖ar和zip的區(qū)別就在于jar中多了一個(gè)META-INF文件夾,如果我們已經(jīng)手動(dòng)添加了,那他們這兩種格式就是一樣了)

此處我們使用手動(dòng)添加META-INF文件夾,然后壓縮zip格式的形式來(lái)完成打包jar的工作,你也可以使用jdk自帶jar命令來(lái)完成打包操作,效果是一樣的。然后我們將此jar包復(fù)制到任意web應(yīng)用的WEB-INF/lib下,這就是web應(yīng)用的所有外部引入包所存放的地方。然后我們啟動(dòng)web容器:

結(jié)果如上,當(dāng)我們請(qǐng)求index,攔截器攔截并調(diào)向default.jsp頁(yè)面。這樣我們就完成了通過(guò)引入外部的jar包而不需要做任何配置,使用了其功能。可能此例并沒(méi)有很好的展示了這種模塊化開(kāi)發(fā)的優(yōu)勢(shì),等到我們學(xué)到框架的時(shí)候就可以很直觀的感受到這種方式的簡(jiǎn)潔,易于攜帶。

三、異步處理

在傳統(tǒng)的servlet開(kāi)發(fā)中,如果servlet調(diào)用了一個(gè)耗時(shí)很長(zhǎng)的邏輯處理方法,那么此servlet必須待在原地等待方法調(diào)用結(jié)束,這是很低效的一種形式。servlet3.0提出了異步處理的概念,也就是釋放了主程序,大大提高了運(yùn)行效率。

Servlet3.0中異步處理主要是通過(guò)接口AsyncContext來(lái)實(shí)現(xiàn)的,我們可以通過(guò)HttpServletRequest對(duì)象來(lái)過(guò)去該接口的實(shí)現(xiàn)對(duì)象。

AsyncContext getAsyncContext();

在使用異步處理之前,我們還需要配置指定當(dāng)前的servlet是支持異步處理。有兩種方法,第一種是在web.xml中配置

<async-supported>true</async-supported>

或者使用webservlet指定屬性asyncSupported=true。下面用一個(gè)實(shí)例演示如何使用servlet的異步處理機(jī)制:

@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 開(kāi)始:"+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();
  }
}

我們可以看到,這個(gè)servlet非常簡(jiǎn)單,截取URL為index的請(qǐng)求,首先打印啟動(dòng)時(shí)間,然后通過(guò)request的startAsync方法創(chuàng)建AsyncContext 對(duì)象,設(shè)置過(guò)期時(shí)間,啟動(dòng)異步處理。這個(gè)線程類代碼如下:

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è)構(gòu)造方法接受AsyncContext 對(duì)象,run方法中,先打印一句話然后結(jié)束異步調(diào)用。我們看看結(jié)果:

通過(guò)時(shí)間我們可以看到servlet開(kāi)始和結(jié)束幾乎同時(shí),而我們的異步處理卻相差三秒鐘,正是我們sleep的三秒鐘。雖然我們實(shí)現(xiàn)了在servlet中異步調(diào)用別的線程來(lái)處理一些邏輯,但是我們還是不能完全控制整個(gè)異步處理中的各個(gè)過(guò)程,比如何時(shí)開(kāi)始,何時(shí)結(jié)束等。Servlet3.0中的AsyncListener接口提供了以下幾個(gè)方法幫助我們監(jiān)控整個(gè)過(guò)程:

  1. onStartAsync(AsyncEvent event) :當(dāng)異步調(diào)用開(kāi)始時(shí)觸發(fā)
  2. onComplete(AsyncEvent event) :當(dāng)異步完成時(shí)觸發(fā)
  3. onError(AsyncEvent event) :當(dāng)異步調(diào)用出錯(cuò)的時(shí)候觸發(fā)
  4. onTimeout(AsyncEvent event):當(dāng)異步調(diào)用超時(shí)時(shí)候觸發(fā)

想要實(shí)現(xiàn)監(jiān)控異步調(diào)用,首先需要編寫一個(gè)類繼承自AsyncListener然后實(shí)現(xiàn)如上四個(gè)方法,之后這個(gè)類就是一個(gè)可以監(jiān)控異步調(diào)用的監(jiān)聽(tīng)器。

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)用超時(shí)了。。。");
  }

  public void onError(AsyncEvent var1) throws IOException{
    System.out.println("異步調(diào)用出錯(cuò)了。。。");
  }

  public void onStartAsync(AsyncEvent var1) throws IOException{
    System.out.println("異步調(diào)用開(kāi)始了。。。");
  }
}

在我們的Servlet主程序中使用以下語(yǔ)句綁定此異步監(jiān)聽(tīng)器:

asy.addListener(new MyAsyncListener());

此時(shí)異步處理的四個(gè)結(jié)點(diǎn)的動(dòng)態(tài),我們都是實(shí)時(shí)掌控的。但是需要注意一點(diǎn)的是:雖然理論上我們是可以監(jiān)聽(tīng)四個(gè)狀態(tài)的,但是其實(shí)異步開(kāi)始這個(gè)事件我們是沒(méi)法監(jiān)聽(tīng)的,也就是異步開(kāi)始的方法永遠(yuǎn)不會(huì)被觸發(fā),原因是在注冊(cè)AsyncContext 的時(shí)候,已經(jīng)開(kāi)始了異步,然而我們卻在注冊(cè)之后才綁定監(jiān)聽(tīng)器,自然是不能監(jiān)聽(tīng)到異步開(kāi)始這個(gè)事件的。

四、文件上傳API

對(duì)于傳統(tǒng)的文件上傳,我們是需要借助于外部工具的,例如:common-fileupload等。自從servlet3.0新規(guī)范以來(lái),改進(jìn)了文件上傳API。

<body>
  <h1>這是index頁(yè)面</h1>
  <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"來(lái)指定,這是一點(diǎn),還有一點(diǎn)就是from標(biāo)簽的enctype屬性,他指定了表單參數(shù)的編碼方式,主要有以下三種:

  1. application/form-data :這是enctype的默認(rèn)值,指定了這個(gè)值就表名表單只會(huì)提交所有input標(biāo)簽中的value值,對(duì)于我們的文件,提交的就是文件名。
  2. multipart/form-data:這種方式是將參數(shù)以二進(jìn)制存儲(chǔ),上傳文件的內(nèi)容也會(huì)被封裝成二進(jìn)制流提交。
  3. text/plain:這種方式主要用于發(fā)送郵件

對(duì)于需要上傳文件功能的我們自然選擇第二個(gè)參數(shù)值,正如上述代碼展示的一樣。下面我們寫一個(gè)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接口來(lái)處理文件上傳,可以通過(guò)HtppServletRequest的以下兩個(gè)方法來(lái)獲取此接口對(duì)象:

Part getPart(String name);
Collection<Part> getParts();

一個(gè)part對(duì)應(yīng)于我們一個(gè)文件上傳域,也就是一個(gè)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集合

在上面的程序中,我們使用了其中一些方法。打印了文件類型,文件名,最后將文件保存到本地桌面上。下面是運(yùn)行的結(jié)果截圖:



綜上就是關(guān)于文件上傳API的基本使用情況,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 解決Java項(xiàng)目中request流只能獲取一次的問(wèn)題

    解決Java項(xiàng)目中request流只能獲取一次的問(wèn)題

    Java項(xiàng)目開(kāi)發(fā)中可能存在以下幾種情況,你需要在攔截器中統(tǒng)一攔截請(qǐng)求和你項(xiàng)目里可能需要搞一個(gè)統(tǒng)一的異常處理器,這兩種情況是比較常見(jiàn)的,本文將給大家介紹如何解決Java項(xiàng)目中request流只能獲取一次的問(wèn)題,需要的朋友可以參考下
    2024-02-02
  • SpringBoot微信消息接口配置詳解

    SpringBoot微信消息接口配置詳解

    這篇文章主要介紹了SpringBoot 微信消息接口配置詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-06-06
  • Java排序算法之SleepSort排序示例

    Java排序算法之SleepSort排序示例

    這篇文章主要介紹了Java排序算法之SleepSort排序,結(jié)合實(shí)例形式分析了SleepSort排序的實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • Java C++ leetcode執(zhí)行一次字符串交換能否使兩個(gè)字符串相等

    Java C++ leetcode執(zhí)行一次字符串交換能否使兩個(gè)字符串相等

    這篇文章主要為大家介紹了Java C++ leetcode1790執(zhí)行一次字符串交換能否使兩個(gè)字符串相等,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • OpenFeign實(shí)現(xiàn)微服務(wù)間的文件下載方式

    OpenFeign實(shí)現(xiàn)微服務(wù)間的文件下載方式

    這篇文章主要介紹了OpenFeign實(shí)現(xiàn)微服務(wù)間的文件下載方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot中全局異常處理的5種實(shí)現(xiàn)方式小結(jié)

    SpringBoot中全局異常處理的5種實(shí)現(xiàn)方式小結(jié)

    在實(shí)際開(kāi)發(fā)中,異常處理是一個(gè)非常重要的環(huán)節(jié),合理的異常處理機(jī)制不僅能提高系統(tǒng)的健壯性,還能大大提升用戶體驗(yàn),下面我們就來(lái)看看SpringBoot中全局異常處理的5種實(shí)現(xiàn)方式吧
    2025-03-03
  • Java 集合中的類關(guān)于線程安全

    Java 集合中的類關(guān)于線程安全

    這篇文章主要介紹了Java 集合中的類關(guān)于線程安全的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Java的SPI機(jī)制以及基于SPI編程示例詳解

    Java的SPI機(jī)制以及基于SPI編程示例詳解

    這篇文章主要為大家介紹了Java的SPI機(jī)制以及基于SPI編程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • 配置javaw.exe雙擊運(yùn)行jar包方式

    配置javaw.exe雙擊運(yùn)行jar包方式

    這篇文章主要介紹了配置javaw.exe雙擊運(yùn)行jar包方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Mybatis實(shí)體類和表映射問(wèn)題(推薦)

    Mybatis實(shí)體類和表映射問(wèn)題(推薦)

    在項(xiàng)目開(kāi)發(fā)中我們經(jīng)常會(huì)遇到表中的字段名和表對(duì)應(yīng)實(shí)體類的屬性名稱不一定都是完全相同的。下面小編給大家介紹下這種情況下如何解決字段名與實(shí)體類屬性名不相同的沖突問(wèn)題。下面小編給大家?guī)?lái)了Mybatis實(shí)體類和表映射的解決方法,小伙伴們一起學(xué)習(xí)吧
    2016-09-09

最新評(píng)論

蛟河市| 荣昌县| 衢州市| 烟台市| 舞钢市| 云和县| 镶黄旗| 扎鲁特旗| 台安县| 廊坊市| 财经| 隆德县| 陆川县| 永善县| 墨脱县| 定南县| 宁晋县| 新津县| 郎溪县| 疏附县| 彭泽县| 濉溪县| 修文县| 綦江县| 梨树县| 蓝山县| 胶州市| 霍邱县| 兴化市| 广东省| 贺兰县| 广元市| 商水县| 塔河县| 德令哈市| 昭通市| 综艺| 鸡西市| 衡山县| 天柱县| 弥渡县|