成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

前言

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

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

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

[[424135]]

所屬專(zhuān)欄

BATutopia-Java EE

相關(guān)下載

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

版本約定

Java EE:6、7、8

Jakarta EE:8、9、9.1

正文

WebSocket

WebSocket是一種在單個(gè)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ì)上是一個(gè)基于TCP的協(xié)議,它由通信協(xié)議和編程API組成,WebSocket能夠在瀏覽器和服務(wù)器之間建立雙向連接,以基于事件的方式,賦予瀏覽器實(shí)時(shí)通信能力。

WebSocket使得客戶端和服務(wù)器之間的數(shù)據(jù)交換變得更加簡(jiǎn)單,允許服務(wù)端主動(dòng)向客戶端推送數(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升級(jí)到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版本號(hào)</version> 
  23. </dependency> 
  24. <dependency> 
  25.     <groupId>org.apache.tomcat</groupId> 
  26.     <artifactId>tomcat-websocket</artifactId> 
  27.     <version>Tomcat版本號(hào)</version> 
  28. </dependency> 

版本歷程

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

  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(shí)推送,也被稱(chēng)作Realtime技術(shù)。這種技術(shù)大大提升交互體驗(yàn),擁有廣泛的應(yīng)用場(chǎng)景:在線聊天(如web版微信)、在線客服系統(tǒng)、評(píng)論系統(tǒng)等等。

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

實(shí)現(xiàn)(框架)

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

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

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

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

代碼示例

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

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

其中client為jar,server為war。

書(shū)寫(xiě)Server端代碼,提供一個(gè)服務(wù)端點(diǎn):

  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)前連接上來(lái)的連接們(每一個(gè)連接都是一個(gè)WsServerDemo實(shí)例,包含一個(gè)Session會(huì)話) 
  13.     private static Set<WsServer> webSocketSet = new CopyOnWriteArraySet<>(); 
  14.     // 會(huì)話 
  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來(lái)自客戶端的消息:" + message); 
  42.         sendMessage("會(huì)話[" + 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ā)生錯(cuò)誤時(shí)調(diào)用 
  55.      */ 
  56.     @OnError 
  57.     public void onError(Throwable error) { 
  58.         System.out.println("Server發(fā)生錯(cuò)誤:" + error.getMessage()); 
  59.     } 
  60.  
  61.     /** 
  62.      * 發(fā)送消息 
  63.      */ 
  64.     public void sendMessage(String message) throws IOException { 
  65.         this.session.getBasicRemote().sendText(message); 
  66.     } 
  67.  

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

使用編程方式書(shū)寫(xiě)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.     // 會(huì)話(與服務(wù)端建立的會(huì)話) 
  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ù)端成功,會(huì)話ID:" + session.getId()); 
  22.         sendMessage("這是一條來(lái)自Client端,會(huì)話["+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會(huì)話" + session.getId() + "已斷開(kāi)"); 
  33.     } 
  34.  
  35.     /** 
  36.      * 發(fā)送消息 
  37.      */ 
  38.     public void sendMessage(String message) throws IOException { 
  39.         this.session.getBasicRemote().sendText(message); 
  40.     } 

用main方法啟動(dòng)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次會(huì)話,端口后再建立新會(huì)話 
  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端控制臺(tái)日志:

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

server端控制臺(tái)日志:

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

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

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

JSTL

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

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

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

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

  1. 1. <c:out>:用于在頁(yè)面輸出 
  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)造一個(gè)URL地址 
  25. 7. <c:set>:設(shè)置數(shù)據(jù) 
  26. 8. <c:remove>:刪除數(shù)據(jù) 
  • 格式化標(biāo)簽:可對(duì)數(shù)字、日期時(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:判斷字符串是否包含另外一個(gè)字符串  
  2.  - <c:if test="${fn:contains(name, searchString)}"
  3. 2. fn:indexOf:子字符串在母字符串中出現(xiàn)的位置  
  4.  - ${fn:indexOf(name'-')} 
  5. 3. fn:toLowerCase:轉(zhuǎn)為小寫(xiě) 
  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ò)展點(diǎn):自定義標(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> 

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

版本歷程

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

JSTL 1.2版本可斷定是最后一個(gè)版本,因?yàn)镴SP已走到盡頭,所以它也會(huì)隨之消亡。

生存現(xiàn)狀

同JSP。

實(shí)現(xiàn)(框架)

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

代碼示例

實(shí)在沒(méi)有應(yīng)用場(chǎng)景了,略。

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

總結(jié)

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

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

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

 

責(zé)任編輯:姜華 來(lái)源: 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谷歌

2025-02-08 10:11:25

2009-07-07 14:33:44

JSP入門(mén)

2011-08-16 16:37:40

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

2021-12-23 06:57:32

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

2022-07-26 14:53:10

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

2011-08-25 14:38:14

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

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

移動(dòng)詐騙電信行業(yè)315晚會(huì)

2010-02-05 10:23:09

C++基本函數(shù)

2010-03-18 16:17:29

Python 變量類(lèi)型

2010-04-15 14:12:20

Oracle 系統(tǒng)操作

2011-08-12 14:39:00

iPhoneSDK
點(diǎn)贊
收藏

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

主站蜘蛛池模板: 天天宗合网 | 国产小视频在线观看 | 在线观看中文字幕视频 | 久久久久久国产 | 少妇av片| 一区二区视频免费观看 | 午夜视频在线免费观看 | 爱操影视 | 国产一区91精品张津瑜 | 一级毛片视频免费观看 | 中文字幕乱码一区二区三区 | 国产精品福利一区二区三区 | 欧美性受 | 噜久寡妇噜噜久久寡妇 | jizjizjiz中国护士18 | 性色综合 | 成人久久一区 | 99热精品在线 | 国产精品污www在线观看 | 亚洲午夜精品一区二区三区他趣 | av在线免费观看网址 | 亚洲高清视频在线观看 | 成人免费高清 | h视频免费在线观看 | 日韩免费网站 | 成人黄色在线视频 | 欧美精品综合 | av在线一区二区三区 | 日韩有码在线播放 | 国产视频一区在线 | 在线成人av | 久久最新网址 | 亚洲人成人一区二区在线观看 | 成人精品一区 | 99小视频 | 成人免费大片黄在线播放 | 精品久久久久一区 | 国产精品久久久亚洲 | 色婷婷综合久久久久中文一区二区 | 武道仙尊动漫在线观看 | 欧美国产日韩在线观看 |