自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

版本歷史&代碼示例之:WebSocket、JSTL

開發(fā) 后端
WebSocket作為長連接的輕量級解決方案,會是B/S的新寵,一舉替掉之前的長輪訓(xùn)等方案。滾滾長江東逝水,這或許就印證著技術(shù)在進(jìn)步,時代在發(fā)展。

前言

你好,我是方同學(xué)(YourBatman)

若你還不太清楚Java EE是什么,可先移步這里:什么是Java EE?

緊接著上一篇講完Servlet、JSP、EL表達(dá)式后,本文嘗試把WebSocket和JSTL再疏通疏通。

[[424135]]

所屬專欄

BATutopia-Java EE

相關(guān)下載

  • 工程源代碼:https://github.com/yourbatman/BATutopia-java-ee
  • 【女媧Knife-Initializr工程】訪問地址:http://152.136.106.14:8761
  • Java開發(fā)軟件包(Mac):https://wangpan.yourbatman.cn/s/rEH0 提取碼:javakit
  • 程序員專用網(wǎng)盤上線啦,開放注冊送1G超小容量,幫你實踐做減法:https://wangpan.yourbatman.cn

版本約定

Java EE:6、7、8

Jakarta EE:8、9、9.1

正文

WebSocket

WebSocket是一種在單個TCP連接上進(jìn)行全雙工通信的協(xié)議。隨著HTML5的誕生,WebSocket通信協(xié)議于2011年被IETF定為標(biāo)準(zhǔn)RFC 6455,并由RFC7936補(bǔ)充規(guī)范。WebSocket API也被W3C定為標(biāo)準(zhǔn)。

WebSocket協(xié)議本質(zhì)上是一個基于TCP的協(xié)議,它由通信協(xié)議和編程API組成,WebSocket能夠在瀏覽器和服務(wù)器之間建立雙向連接,以基于事件的方式,賦予瀏覽器實時通信能力。

WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡單,允許服務(wù)端主動向客戶端推送數(shù)據(jù)。在WebSocket API中,瀏覽器和服務(wù)器只需要完成一次握手,兩者之間就直接可以創(chuàng)建持久性的連接,并進(jìn)行雙向數(shù)據(jù)傳輸。工作流程如下圖:

Java API for WebSocket是Java的Web套接字,在2013年6月份伴隨著Java EE 7推出(1.0版本),Java EE 8升級到1.1版本。

注意:WebSocket的Client可以是瀏覽器,也可是WebSocket的終端(如Java應(yīng)用、Go應(yīng)用)。

  1. <!-- javax命名空間版本(Tomcat 9.x及以下版本支持) --> 
  2. <dependency> 
  3.     <groupId>javax.websocket</groupId> 
  4.     <artifactId>javax.websocket-api</artifactId> 
  5.     <version>1.1</version> 
  6.     <scope>provided</scope> 
  7. </dependency> 
  8.  
  9. <!-- jakarta命名空間版本(Tomcat 10.x及以上版本支持) --> 
  10. <dependency> 
  11.     <groupId>jakarta.websocket</groupId> 
  12.     <artifactId>jakarta.websocket-api</artifactId> 
  13.     <version>2.0.0</version> 
  14.     <!-- <version>1.1.2</version> 此版本命名空間同javax --> 
  15.     <scope>provided</scope> 
  16. </dependency> 
  17.  
  18. 除此之外,一般情況下我們直接使用Web容器提供的Jar即可,如Tomcat 
  19. <dependency> 
  20.     <groupId>org.apache.tomcat.embed</groupId> 
  21.     <artifactId>tomcat-embed-websocket</artifactId> 
  22.     <version>Tomcat版本號</version> 
  23. </dependency> 
  24. <dependency> 
  25.     <groupId>org.apache.tomcat</groupId> 
  26.     <artifactId>tomcat-websocket</artifactId> 
  27.     <version>Tomcat版本號</version> 
  28. </dependency> 

版本歷程

servlet-3.1版本開始支持。WebSocket 1.1 版與 1.0 版完全向后兼容,只在javax.websocket.Session中添加了兩個方法:

  1. <T> void addMessageHandler(Class<T> clazz, MessageHandler.Partial<T> handler) throws IllegalStateException; 
  2. <T> void addMessageHandler(Class<T> clazz, MessageHandler.Whole<T> handler) throws IllegalStateException; 

生存現(xiàn)狀

作為Http協(xié)議的“補(bǔ)充”,很好的彌補(bǔ)了其不足,在Web領(lǐng)域?qū)崟r推送,也被稱作Realtime技術(shù)。這種技術(shù)大大提升交互體驗,擁有廣泛的應(yīng)用場景:在線聊天(如web版微信)、在線客服系統(tǒng)、評論系統(tǒng)等等。

總的來講,WebSocket作為新貴,生存現(xiàn)狀挺好,前景一片光明。

實現(xiàn)(框架)

WebSocket其實是構(gòu)建在Http協(xié)議之上的,所以對于Java語言來講它依舊由Web容器來提供實現(xiàn)。

概念區(qū)分:Web容器不一定是Servlet容器,而Servlet容器一定是Web容器

除此之外也有獨(dú)立實現(xiàn):

  • client端實現(xiàn):org.eclipse.jetty.websocket:javax-websocket-client-impl
  • server端實現(xiàn):org.eclipse.jetty.websocket:javax-websocket-server-impl對于Client來講,一般都是瀏覽器。

代碼示例

前面有提到,WebSocket的Client端既可以是瀏覽器(現(xiàn)代的瀏覽器100%都支持此協(xié)議,若需要考慮瀏覽器兼容問題(比如國外現(xiàn)在依舊有使用老版IE瀏覽器的),可以使用socketio框架哈),也可以是Java應(yīng)用。本示例就加點“難度”,用Java應(yīng)用作為WebSocket的客戶端。當(dāng)然嘍,服務(wù)端肯定也是Java應(yīng)用呀。

創(chuàng)建demo項目,結(jié)構(gòu)如下:

其中client為jar,server為war。

書寫Server端代碼,提供一個服務(wù)端點:

  1. /** 
  2.  * 在此處添加備注信息 
  3.  * 
  4.  * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a> 
  5.  * @site https://yourbatman.cn 
  6.  * @date 2021/9/12 15:29 
  7.  * @since 0.0.1 
  8.  */ 
  9. @ServerEndpoint("/websocket/chat"
  10. public class WsServer { 
  11.  
  12.     // 當(dāng)前連接上來的連接們(每一個連接都是一個WsServerDemo實例,包含一個Session會話) 
  13.     private static Set<WsServer> webSocketSet = new CopyOnWriteArraySet<>(); 
  14.     // 會話 
  15.     private Session session; 
  16.  
  17.     /** 
  18.      * 建連成功的回調(diào) 
  19.      */ 
  20.     @OnOpen 
  21.     public void onOpen(Session session) { 
  22.         this.session = session; 
  23.         webSocketSet.add(this); // 保存當(dāng)前連接 
  24.         System.out.println("Server有新連接加入!當(dāng)前在線人數(shù)為" + webSocketSet.size()); 
  25.     } 
  26.  
  27.     /** 
  28.      * 連接關(guān)閉調(diào)用的方法 
  29.      */ 
  30.     @OnClose 
  31.     public void onClose() { 
  32.         webSocketSet.remove(this); 
  33.         System.out.println("Server有一連接關(guān)閉!當(dāng)前在線人數(shù)為" + webSocketSet.size()); 
  34.     } 
  35.  
  36.     /** 
  37.      * 收到客戶端消息后調(diào)用的方法 
  38.      */ 
  39.     @OnMessage 
  40.     public void onMessage(String message) throws IOException { 
  41.         System.out.println("Server來自客戶端的消息:" + message); 
  42.         sendMessage("會話[" + session.getId() + "]的消息已經(jīng)收到,內(nèi)容為:" + message); 
  43.         // // =======群發(fā)消息========= 
  44.         // for (WsServerDemo item : webSocketSet) { 
  45.         //     try { 
  46.         //         item.sendMessage(message); 
  47.         //     } catch (IOException e) { 
  48.         //         continue
  49.         //     } 
  50.         // } 
  51.     } 
  52.  
  53.     /** 
  54.      * 發(fā)生錯誤時調(diào)用 
  55.      */ 
  56.     @OnError 
  57.     public void onError(Throwable error) { 
  58.         System.out.println("Server發(fā)生錯誤:" + error.getMessage()); 
  59.     } 
  60.  
  61.     /** 
  62.      * 發(fā)送消息 
  63.      */ 
  64.     public void sendMessage(String message) throws IOException { 
  65.         this.session.getBasicRemote().sendText(message); 
  66.     } 
  67.  

我這里簡便起見,使用web容器直接實現(xiàn)。有興趣/想深究websocket的同學(xué),可使用org.eclipse.jetty.websocket:javax-websocket-server-impl通過API方式去啟動Server,本文只演示用該方式啟動client哈,二者兼顧嘛。

使用編程方式書寫client端代碼:

  1. /** 
  2.  * 在此處添加備注信息 
  3.  * 
  4.  * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a> 
  5.  * @site https://yourbatman.cn 
  6.  * @date 2021/9/12 15:31 
  7.  * @since 0.0.1 
  8.  */ 
  9. @ClientEndpoint 
  10. public class WsClient { 
  11.  
  12.     // 會話(與服務(wù)端建立的會話) 
  13.     private Session session; 
  14.  
  15.     /** 
  16.      * 建連成功的回調(diào) 
  17.      */ 
  18.     @OnOpen 
  19.     public void onOpen(Session session) throws IOException { 
  20.         this.session = session; 
  21.         System.out.println("Client連接到服務(wù)端成功,會話ID:" + session.getId()); 
  22.         sendMessage("這是一條來自Client端,會話["+session.getId()+"]的消息"); 
  23.     } 
  24.  
  25.     @OnMessage 
  26.     public void onMessage(String message) { 
  27.         System.out.println("Client端收到消息: " + message); 
  28.     } 
  29.  
  30.     @OnClose 
  31.     public void onClose() { 
  32.         System.out.println("Client會話" + session.getId() + "已斷開"); 
  33.     } 
  34.  
  35.     /** 
  36.      * 發(fā)送消息 
  37.      */ 
  38.     public void sendMessage(String message) throws IOException { 
  39.         this.session.getBasicRemote().sendText(message); 
  40.     } 

用main方法啟動Client端,去連接Server端并發(fā)送消息:

  1. public class ClientApp { 
  2.  
  3.     private static URI uri = URI.create("ws://localhost:8080/websocket/chat"); 
  4.     private static Session session; 
  5.  
  6.     public static void main(String[] args) throws DeploymentException, IOException, InterruptedException { 
  7.         WebSocketContainer container = ContainerProvider.getWebSocketContainer(); 
  8.  
  9.         // 順序執(zhí)行5次會話,端口后再建立新會話 
  10.         for (int i = 0; i < 5; i++) { 
  11.             session = container.connectToServer(WsClient.class, uri); 
  12.             session.close(); 
  13.             TimeUnit.SECONDS.sleep(2); 
  14.         } 
  15.     } 

client端控制臺日志:

  1. Client連接到服務(wù)端成功,會話ID:1 
  2. Client端收到消息: 會話[0]的消息已經(jīng)收到,內(nèi)容為:這是一條來自Client端,會話[1]的消息 
  3. Client會話1已斷開 
  4. Client連接到服務(wù)端成功,會話ID:2 
  5. Client端收到消息: 會話[1]的消息已經(jīng)收到,內(nèi)容為:這是一條來自Client端,會話[2]的消息 
  6. Client會話2已斷開 
  7. Client連接到服務(wù)端成功,會話ID:3 
  8. Client端收到消息: 會話[2]的消息已經(jīng)收到,內(nèi)容為:這是一條來自Client端,會話[3]的消息 
  9. Client會話3已... 

server端控制臺日志:

  1. Server有新連接加入!當(dāng)前在線人數(shù)為1 
  2. Server來自客戶端的消息:這是一條來自Client端,會話[1]的消息 
  3. Server有一連接關(guān)閉!當(dāng)前在線人數(shù)為0 
  4. Server有新連接加入!當(dāng)前在線人數(shù)為1 
  5. Server來自客戶端的消息:這是一條來自Client端,會話[2]的消息 
  6. Server有一連接關(guān)閉!當(dāng)前在線人數(shù)為0 
  7. Server有新連接加入!當(dāng)前在線人數(shù)為1 
  8. Server來自客戶端的消息:這是一條來自Client端,會話[3]的消息 
  9. Server有一連接關(guān)閉!當(dāng)前在線人數(shù)為0 

說明:本文特意使用Java應(yīng)用作為Client端是想讓你更深刻的理解WebSocket的用法,實際場景中,其實大都是B/S模式,通過JavaScript作為客戶端建立連接(相對簡單)。

工程源代碼:https://github.com/yourbatman/BATutopia-java-ee

JSTL

Java server pages standarded tag library,即JSP標(biāo)準(zhǔn)標(biāo)簽庫。主要提供給Java Web開發(fā)人員一個標(biāo)準(zhǔn)通用的標(biāo)簽庫,開發(fā)人員可以利用這些標(biāo)簽取代 JSP頁面上的Java代碼,從而提高程序的可讀性,降低程序的維護(hù)難度。

JSTL強(qiáng)依賴于JSP的存在而存在。

JSTL和EL表達(dá)式的目的是一樣的:取代JSP頁面上寫Java代碼。它比EL更為強(qiáng)大些,可以完成一些結(jié)構(gòu)化邏輯任務(wù),如:迭代、條件判斷、XML文檔操作、國際化、SQL等,下面簡要介紹其主要標(biāo)簽。

  • 核心標(biāo)簽:也是著名C標(biāo)簽。在JSP文件開頭引入c標(biāo)簽<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>,支持的常用函數(shù)有:

  1. 1. <c:out>:用于在頁面輸出 
  2.  - <c:out value="expression" default="expression" escapeXml="boolean"/> 
  3. 2. <c:if>:邏輯判斷 
  4.  - <c:if test="expression" var="name" scope="scope">   
  5.        body content   
  6.    </c:if> 
  7. 3. <c:choose>:邏輯判斷。when和otherwise的父標(biāo)簽 
  8. 4. <c:when>: <c:otherwise>: 
  9.  - <c:choose>   
  10.      <c:when test="expression">   
  11.          body content   
  12.      </c:when>   
  13.   ... 
  14.      <c:otherwise>   
  15.       body content   
  16.   </c:otherwise>   
  17.    </c:choose> 
  18.   
  19. 5. <c:foreach>: 
  20.  - <c:forEach var="name" items="expression" varStatus="name" begin="expression" end="expression" step="expression">   
  21.        body content   
  22.    </c:forEach> 
  23.  
  24. 6. <c:url>:使用可選的查詢參數(shù)創(chuàng)造一個URL地址 
  25. 7. <c:set>:設(shè)置數(shù)據(jù) 
  26. 8. <c:remove>:刪除數(shù)據(jù) 
  • 格式化標(biāo)簽:可對數(shù)字、日期時間等格式化。<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>,主要函數(shù):

  1. 1. <fmt:formatNumber>:格式化數(shù)字 
  2. 2. <fmt:parseNumber>:解析字符串到數(shù)字、貨幣、百分比 
  3. 3. <fmt:formatDate>: 
  4. 4. <fmt:parseData>: 
  • JSTL函數(shù):一般用于輔助標(biāo)簽控制行為。<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>,主要函數(shù):

  1. 1. fn:contains:判斷字符串是否包含另外一個字符串  
  2.  - <c:if test="${fn:contains(name, searchString)}"
  3. 2. fn:indexOf:子字符串在母字符串中出現(xiàn)的位置  
  4.  - ${fn:indexOf(name'-')} 
  5. 3. fn:toLowerCase:轉(zhuǎn)為小寫 
  6.  - ${fn.toLowerCase(product.name)} 
  • SQL標(biāo)簽,<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>。主要函數(shù):
  1. 1. <sql:setDataSource>、<sql:query>、<sql:update

  • XML標(biāo)簽,<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>。主要函數(shù):
  1. 1. <x:parse>、<x:if>、<x:forEach> 

除此之外,還提供了擴(kuò)展點:自定義標(biāo)簽。

  1. <!-- javax命名空間版本(Tomcat 9.x及以下版本支持) --> 
  2. <dependency> 
  3.     <groupId>javax.servlet.jsp.jstl</groupId> 
  4.     <artifactId>jstl-api</artifactId> 
  5.     <version>1.2</version> 
  6. </dependency> 
  7.  
  8. <!-- jakarta命名空間版本(Tomcat 10.x及以上版本支持) --> 
  9. <dependency> 
  10.     <groupId>jakarta.servlet.jsp.jstl</groupId> 
  11.     <artifactId>jakarta.servlet.jsp.jstl-api</artifactId> 
  12.     <version>2.0.0</version> 
  13.     <!-- <version>1.2.7</version> 此版本命名空間同javax --> 
  14. </dependency> 

說明:之前可能需要有jstl.jar和standard.jar兩個Jar,但從1.2版本后這一個GAV即可。當(dāng)然嘍,99.99%情況下該jar無需你導(dǎo)入,由web容器負(fù)責(zé)

版本歷程

JSTL也依賴于JSP而存在,所以和JSP版本有強(qiáng)關(guān)系。

JSTL 1.2版本可斷定是最后一個版本,因為JSP已走到盡頭,所以它也會隨之消亡。

生存現(xiàn)狀

同JSP。

實現(xiàn)(框架)

與Servlet相同的Web容器,由Web容器提供解析能力。如tomcat的標(biāo)簽庫實現(xiàn):http://tomcat.apache.org/taglibs

代碼示例

實在沒有應(yīng)用場景了,略。

工程源代碼:https://github.com/yourbatman/BATutopia-java-ee

總結(jié)

WebSocket作為長連接的輕量級解決方案,會是B/S的新寵,一舉替掉之前的長輪訓(xùn)等方案。滾滾長江東逝水,這或許就印證著技術(shù)在進(jìn)步,時代在發(fā)展。

作為老一輩程序員的我,對EL表達(dá)式、JSTL這類技術(shù)依舊有記憶存留,但新時代的程序員可能沒有必要再接觸。本文就當(dāng)做自留地,封存這段學(xué)習(xí)的記憶吧。

本文轉(zhuǎn)載自微信公眾號「BAT的烏托邦」

 

責(zé)任編輯:姜華 來源: BAT的烏托邦
相關(guān)推薦

2021-10-19 08:23:43

JMXJava 管理擴(kuò)展

2021-10-11 08:51:50

JavaMailJDBCJava

2021-10-08 06:50:32

版本歷史代碼

2021-09-13 18:39:50

ServeltELJSP

2021-10-25 08:16:20

Java JAX-RS Java 基礎(chǔ)

2017-10-31 12:56:52

Androidios谷歌

2009-07-07 14:33:44

JSP入門

2025-02-08 10:11:25

2011-08-16 16:37:40

Oracle數(shù)據(jù)庫樹形查詢根節(jié)點

2021-12-23 06:57:32

數(shù)據(jù)通信Websocket

2011-08-25 14:38:14

SQL Server修改表結(jié)構(gòu)字段類型

2022-07-26 14:53:10

WebSocket網(wǎng)絡(luò)通信協(xié)議

2018-01-02 13:30:04

代碼質(zhì)量代碼預(yù)言

2010-01-28 16:01:18

Android Jni

2012-04-19 14:41:39

安騰惠普HP

2015-03-16 10:12:15

移動詐騙電信行業(yè)315晚會

2021-10-25 10:40:03

Java開發(fā)微服務(wù)

2010-08-30 09:56:09

IP dhcp sno

2010-02-05 10:23:09

C++基本函數(shù)

2011-08-12 14:39:00

iPhoneSDK
點贊
收藏

51CTO技術(shù)棧公眾號