一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 詳解Servlet3.0新特性(從注解配置到websocket編程)

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

2020-09-17 15:48Walker_YAM Java教程

Servlet3.0的出現是servlet史上最大的變革,其中的許多新特性大大的簡化了web應用的開發,為廣大勞苦的程序員減輕了壓力,提高了web開發的效率。

servlet3.0的出現是servlet史上最大的變革,其中的許多新特性大大的簡化了web應用的開發,為廣大勞苦的程序員減輕了壓力,提高了web開發的效率。主要新特性有以下幾個:

  1. 引入注解配置
  2. 支持web模塊化開發
  3. 程序異步處理
  4. 改進文件上傳api
  5. 非阻塞式io讀取流
  6. websocket實時通信

一、注解配置

servlet3.0新規范順應了時代的潮流,使用注解配置,取代混亂的web.xml全局配置。在這之前我們在創建servlet,filter,listener時,都是在web.xml中配置。

?
1
2
3
4
5
6
7
8
9
//創建一個servlet需要在web.xml中配置如下內容
<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>
?
1
2
3
4
5
6
7
8
9
10
11
12
//我們只使用一行代碼完成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);
  }
}

關于filter和listener的注解配置方法和上述形式一樣,在3.0新規范中主要提供了以下一些注解用于配置:

  1. websocket :用于配置socket
  2. webinitparam :用于配置初始化參數,往往和servlet和filter結合使用
  3. weblistener :用于配置listener
  4. webfilter :用于配置filter
  5. multipartconfig :用于文件上傳(后面會詳細介紹)

還有一些,暫時沒有涉及,就不列舉了

二、servlet3.0 web模塊化開發

在這之前我們對于web應用中的各個servlet,filter,listener都是需要在web.xml中進行配置,如果只是本項目中的各個點的配置,那倒還好,但是如果我們引入框架,是不是每個框架中的各種配置也是需要在我們的web.xml中配置?這無疑會導致我們唯一的web.xml中內容混亂。servlet3.0新規范提出了模塊化開發,也就是每個servlet,filter,listener都可以有屬于自己的配置文件,功能和web.xml一樣,它只負責配置當前的servlet。然后我們只需要將配置文件和自己寫的servlet等內容打包成jar,引入到具體項目中即可。(就像我們想要使用了某個功能,引入了從網上下載的jar包到項目中)下面我們看如何使用,由于servlet,filter,listener的配置類似,此處以servlet為例作為演示:

首先我們寫一個servlet類:

?
1
2
3
4
5
6
7
8
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);
  }
}

然后我們創建一個web-fragment.xml文件,這就是屬于此servlet自己的配置文件,功能類似于web.xml,只是這個是私有的。鍵入以下內容:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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,別處幾乎一樣。我們創建的這個servlet主要負責攔截url為index的請求,并轉向default.jsp頁面。

接下來我們看如何打包jar,然后再次為我們項目使用。第一步,無論你是用javac命令還是用ide編譯,首先我們需要將此.java文件編譯成class文件。在你的電腦的任意位置創建一個空文件夾,將編譯后的class文件及其包復制進去,因為我們myservlet在test包下,此處我就是將test文件夾復制進去(你們需要根據自己建立的文件進行操作)

然后創建一個空文件夾,命名為meta-inf,一定要這樣命名,因為等我們把jar包引入到項目中之后,一旦web應用啟動時,就會去我們引入的jar包的此文件夾下查找web-fragment.xml文件并加載,如果沒有找到就不會加載,我們的配置也就不會生效。此時我們文件夾中的內容如下:

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

將剛剛寫完的web-fragment.xml文件復制到meta-inf下,然后我們將這兩個文件夾壓縮成zip格式,然后修改zip為jar即可(因為jar和zip的區別就在于jar中多了一個meta-inf文件夾,如果我們已經手動添加了,那他們這兩種格式就是一樣了)

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

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

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

結果如上,當我們請求index,攔截器攔截并調向default.jsp頁面。這樣我們就完成了通過引入外部的jar包而不需要做任何配置,使用了其功能。可能此例并沒有很好的展示了這種模塊化開發的優勢,等到我們學到框架的時候就可以很直觀的感受到這種方式的簡潔,易于攜帶。

三、異步處理

在傳統的servlet開發中,如果servlet調用了一個耗時很長的邏輯處理方法,那么此servlet必須待在原地等待方法調用結束,這是很低效的一種形式。servlet3.0提出了異步處理的概念,也就是釋放了主程序,大大提高了運行效率。

servlet3.0中異步處理主要是通過接口asynccontext來實現的,我們可以通過httpservletrequest對象來過去該接口的實現對象。

?
1
asynccontext getasynccontext();

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

?
1
<async-supported>true</async-supported>

或者使用webservlet指定屬性asyncsupported=true。下面用一個實例演示如何使用servlet的異步處理機制:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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 結束:"+new date()+"<br />");
    writer.flush();
  }
}

我們可以看到,這個servlet非常簡單,截取url為index的請求,首先打印啟動時間,然后通過request的startasync方法創建asynccontext 對象,設置過期時間,啟動異步處理。這個線程類代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();
    }
  }
}

一個構造方法接受asynccontext 對象,run方法中,先打印一句話然后結束異步調用。我們看看結果:

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

通過時間我們可以看到servlet開始和結束幾乎同時,而我們的異步處理卻相差三秒鐘,正是我們sleep的三秒鐘。雖然我們實現了在servlet中異步調用別的線程來處理一些邏輯,但是我們還是不能完全控制整個異步處理中的各個過程,比如何時開始,何時結束等。servlet3.0中的asynclistener接口提供了以下幾個方法幫助我們監控整個過程:

  1. onstartasync(asyncevent event) :當異步調用開始時觸發
  2. oncomplete(asyncevent event) :當異步完成時觸發
  3. onerror(asyncevent event) :當異步調用出錯的時候觸發
  4. ontimeout(asyncevent event):當異步調用超時時候觸發

想要實現監控異步調用,首先需要編寫一個類繼承自asynclistener然后實現如上四個方法,之后這個類就是一個可以監控異步調用的監聽器。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class myasynclistener implements asynclistener {
 
  public void oncomplete(asyncevent var1) throws ioexception{
    system.out.println("異步調用結束了。。。");
  }
 
  public void ontimeout(asyncevent var1) throws ioexception{
    system.out.println("異步調用超時了。。。");
  }
 
  public void onerror(asyncevent var1) throws ioexception{
    system.out.println("異步調用出錯了。。。");
  }
 
  public void onstartasync(asyncevent var1) throws ioexception{
    system.out.println("異步調用開始了。。。");
  }
}

在我們的servlet主程序中使用以下語句綁定此異步監聽器:

?
1
asy.addlistener(new myasynclistener());

此時異步處理的四個結點的動態,我們都是實時掌控的。但是需要注意一點的是:雖然理論上我們是可以監聽四個狀態的,但是其實異步開始這個事件我們是沒法監聽的,也就是異步開始的方法永遠不會被觸發,原因是在注冊asynccontext 的時候,已經開始了異步,然而我們卻在注冊之后才綁定監聽器,自然是不能監聽到異步開始這個事件的。

四、文件上傳api

對于傳統的文件上傳,我們是需要借助于外部工具的,例如:common-fileupload等。自從servlet3.0新規范以來,改進了文件上傳api。

?
1
2
3
4
5
6
7
8
<body>
  <h1>這是index頁面</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"來指定,這是一點,還有一點就是from標簽的enctype屬性,他指定了表單參數的編碼方式,主要有以下三種:

  1. application/form-data :這是enctype的默認值,指定了這個值就表名表單只會提交所有input標簽中的value值,對于我們的文件,提交的就是文件名。
  2. multipart/form-data:這種方式是將參數以二進制存儲,上傳文件的內容也會被封裝成二進制流提交。
  3. text/plain:這種方式主要用于發送郵件

對于需要上傳文件功能的我們自然選擇第二個參數值,正如上述代碼展示的一樣。下面我們寫一個servlet用于處理上傳的信息。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@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的以下兩個方法來獲取此接口對象:

?
1
2
part getpart(string name);
collection<part> getparts();

一個part對應于我們一個文件上傳域,也就是一個input類型為file的元素。part中有以下一些方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
string getcontenttype();  //返回文件類型,如image/png
 
string getname();     //返回文件名
 
string getsubmittedfilename();
 
long getsize();     //返回文件的大小
 
void write(string var1) throws ioexception;  //將文件寫入到服務器磁盤
 
void delete() throws ioexception;     //刪除此文件
 
string getheader(string var1);      //獲取指定文件名的值
 
collection<string> getheaders(string var1); //獲取指定文件名的所有的值
 
collection<string> getheadernames();  //獲取所有header 的name集合

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

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

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

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

綜上就是關于文件上傳api的基本使用情況,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.cnblogs.com/yangming1996/p/6745531.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产成人精品视频一区二区不卡 | 单亲乱l仑在线观看免费观看 | 日韩一级欧美一级一级国产 | 欧美一级特黄特色大片 | 国产日韩免费视频 | 亚洲精品国产精品精 | 波多野结衣中文字幕乱七八糟 | v视界影院成片 | 国产成人看片免费视频观看 | 日韩欧美视频二区 | 不卡一区二区三区 | 妹妹你插的我好爽 | 国产亚洲玖玖玖在线观看 | 四虎影院的网址 | 四虎1515hh.com| 水野朝阳厨房系列在线观看 | a黄色| 啪啪大幂幂被c | 西施打开双腿下面好紧 | 精品视频在线观看免费 | 欧美成人福利 | 大团圆6全文在线阅读 | 视频免费视频观看网站 | 国产在线拍| 爱爱一级视频 | 国产欧美日韩不卡一区二区三区 | 美国大片成人性网 | 91国内精品久久久久怡红院 | 亚洲国产视频一区 | 性派对videofreeparty | 99网站在线观看 | 日本不卡一区二区三区在线观看 | 香蕉在线精品亚洲第一区 | 99久久久久国产精品免费 | 国产精品片 | 青春学堂在线观看 | 国产a一级毛片爽爽影院 | 国产天天在线 | 亚洲视频久久 | 精品国产线拍大陆久久尤物 | 亚洲国产在线2o20 |