詳細(xì)SpringBoot框架教程——SpringBoot集成websocket

本篇文章主要內(nèi)容
SpringBoot集成websocket
注冊(cè)Servlets, Filters, Listeners作為Spring Beans
SpringBoot使用攔截器
SpringBoot內(nèi)嵌Web服務(wù)器
SpringBoot打包部署
視頻觀看戳??????

SpringBoot集成websocket
WebSocket協(xié)議是由HTML5定義的,基于TCP協(xié)議實(shí)現(xiàn)的一種網(wǎng)絡(luò)協(xié)議,通過該協(xié)議服務(wù)器可以主動(dòng)向客戶端發(fā)送信息;
WebSocket 協(xié)議在2008年誕生,2011年成為W3C國際標(biāo)準(zhǔn);
我們已經(jīng)有了 HTTP 協(xié)議,為什么出現(xiàn)一個(gè)websocket協(xié)議?
http協(xié)議是短連接,因?yàn)檎?qǐng)求之后,都會(huì)關(guān)閉連接,下次重新請(qǐng)求數(shù)據(jù),需要再次打開鏈接;
WebSocket協(xié)議是一種長(zhǎng)連接,只需要通過一次請(qǐng)求來初始化連接,然后所有的請(qǐng)求和響應(yīng)都是通過這個(gè)TCP連接進(jìn)行通訊;
所以HTTP協(xié)議通信只能是客戶端向服務(wù)器發(fā)出請(qǐng)求,服務(wù)器返回響應(yīng)結(jié)果,HTTP 協(xié)議做不到服務(wù)器主動(dòng)向客戶端推送信息,而websocket能實(shí)現(xiàn)服務(wù)器和客戶端全雙工通信;
何謂全雙工
信息只能單向傳送為單工;信息能雙向傳送但不能同時(shí)雙向傳送稱為半雙工,信息能夠同時(shí)雙向傳送則稱為全雙工;
基本實(shí)現(xiàn)原理
WebSocket協(xié)議基于TCP協(xié)議實(shí)現(xiàn),客戶端和服務(wù)器只需要做一個(gè)握手的動(dòng)作之后,形成了一條基于客戶端和服務(wù)器之間的快速通道,之后客戶端與服務(wù)端之間便可以進(jìn)行多次數(shù)據(jù)幀雙向傳輸;
這樣實(shí)現(xiàn)的目的是客戶端和服務(wù)器進(jìn)行頻繁雙向通信時(shí),可以使服務(wù)器避免頻繁創(chuàng)建HTTP連接,節(jié)約資源,提高工作效率和資源利用率;
傳統(tǒng)Web推送實(shí)現(xiàn)
在沒有WebSocket協(xié)議之前,服務(wù)器如何向?yàn)g覽器端推送消息?
此時(shí),通常的實(shí)現(xiàn)方式是在頁面通過Ajax定時(shí)輪詢,比如每隔1秒中向服務(wù)器發(fā)送一次HTTP請(qǐng)求,詢問服務(wù)器是否有新消息,服務(wù)器返回結(jié)果;
這種形式缺點(diǎn)很明顯,瀏覽器需要不斷的向服務(wù)器發(fā)出HTTP請(qǐng)求,而HTTP請(qǐng)求包含較長(zhǎng)的頭部,有效信息相對(duì)較少,反復(fù)的無效請(qǐng)求占用了大量的帶寬和 CPU 資源,造成很大的浪費(fèi),所以,WebSocket 應(yīng)運(yùn)而生;
HTML5定義的WebSocket協(xié)議,能更好的節(jié)省服務(wù)器資源和帶寬,并且能夠更實(shí)時(shí)地進(jìn)行通訊;
WebSocket協(xié)議本質(zhì)上是一個(gè)基于TCP的協(xié)議,因此與HTTP協(xié)議沒有什么關(guān)系;
WebSocket的特點(diǎn)
全雙工通信,客戶端和服務(wù)器可以雙向平等通信;
建立在TCP協(xié)議之上,服務(wù)器端的實(shí)現(xiàn)比較容易;
數(shù)據(jù)格式比較輕量,性能開銷小,通信高效;
可以發(fā)送文本,也可以發(fā)送二進(jìn)制數(shù)據(jù);
通信具有更強(qiáng)的實(shí)時(shí)性;
協(xié)議標(biāo)識(shí)符是ws,服務(wù)器地址就是:ws://www.abc.com/some/path
http協(xié)議: http://
websocket業(yè)務(wù)場(chǎng)景
WebSocket聊天室;
股票實(shí)時(shí)價(jià)格顯示等應(yīng)用;
即時(shí)通訊、游戲、可視化大屏展示等領(lǐng)域;
企業(yè)內(nèi)部管理通訊等功能,主要通訊協(xié)議websocket;
web網(wǎng)頁聊天、客服系統(tǒng)實(shí)現(xiàn);
系統(tǒng)提醒、用戶上下線提醒、客戶端同步,實(shí)時(shí)數(shù)據(jù)更新,多屏幕同步,用戶在線狀態(tài),消息通知,掃描二維碼登錄/二維碼支付,彈幕、各類信息提醒,在線選座,實(shí)時(shí)監(jiān)控大屏等等;
Java中的WebSocket API
在Java?EE?7中Java語言開始支持websocket協(xié)議,Java EE 7中定義了一套Websocket?API規(guī)范,也就是一系列接口,沒有實(shí)現(xiàn),位于包javax.websocket下,包含客戶端API和服務(wù)端API,WebSocket的Java API 只是規(guī)范,具體實(shí)現(xiàn)需要web容器(比如tomcat就實(shí)現(xiàn)了Java websocket api)、Java?EE服務(wù)器或者框架提供;
現(xiàn)在最新版本是Oracle Java EE 8; 以后的Java EE版本升級(jí)是eclipse去做,以后Oracle就不管Java EE的維護(hù)和升級(jí);

在Java中服務(wù)端的實(shí)現(xiàn)
1、Tomcat:java中的websocket實(shí)現(xiàn),需要tomcat 7.0.47+以上才支持,Java EE7的支持;
2、Spring的websocket,需要Spring 4.x,所以springboot也可以用;
Websocket開發(fā)相關(guān)注解及API方法
@ServerEndpoint("/websocket/{uid}")
申明這是一個(gè)websocket服務(wù);
需要指定訪問該服務(wù)的地址,在地址中可以指定參數(shù),需要通過{}進(jìn)行占位;
?
@OnOpen
用法:public void onOpen(Session session, @PathParam("uid") String uid) throws IOException{}
該方法將在建立連接后執(zhí)行,會(huì)傳入session對(duì)象,就是客戶端與服務(wù)端建立的長(zhǎng)連接通道,通過@PathParam獲取url中聲明的參數(shù);
?
@OnClose
用法:public void onClose() {}
該方法是在連接關(guān)閉后執(zhí)行;
?
@OnMessage
用法:public void onMessage(String message, Session session) throws IOException {}
該方法用于接收客戶端發(fā)送的消息;
message:發(fā)來的消息數(shù)據(jù);
session:會(huì)話對(duì)象(也是長(zhǎng)連接通道);
發(fā)送消息到客戶端;
用法:session.getBasicRemote().sendText("hello,websocket.");
通過session進(jìn)行消息發(fā)送;
前端技術(shù)對(duì)websocket的支持
Websocket是html5規(guī)范,主流瀏覽器都支持;(某些老瀏覽器不支持)
jQuery、vueJS、React?JS、angularjs等都可以支持webscoket對(duì)象;
底層是javascript支持的一個(gè)webscoket的js對(duì)象,通過這個(gè)對(duì)象可以建立websocket的連接:ws://localhost:8080/websocket/12345?
第三方商業(yè)方案goeasy
GoEasy實(shí)時(shí)Web推送,支持后臺(tái)推送和前臺(tái)推送兩種:后臺(tái)推送可以選擇Java SDK、Restful API支持所有開發(fā)語言;前臺(tái)推送:JS推送,由于它支持websocket 和polling兩種連接方式所以兼顧大多數(shù)主流瀏覽器,低版本的IE瀏覽器也是支持的;
地址:http://goeasy.io/?
?
WebSocket有很多優(yōu)點(diǎn),彌補(bǔ)了http協(xié)議的不足,但是如果服務(wù)端維護(hù)很多長(zhǎng)連接也是很耗費(fèi)資源的,服務(wù)器集群帶來了復(fù)雜性以及存在老版本瀏覽器兼容性問題,各大廠目前大多數(shù)還是基于輪詢的方式實(shí)現(xiàn)的,比如:掃碼登錄、支付成功通知、秒殺成功通知等;
在秒殺場(chǎng)景中,用輪詢即可,前端輪詢一般不可能穿透到后端數(shù)據(jù)庫查詢,一般是采用高性能的緩存標(biāo)記來判定秒殺是否成功,相對(duì)于websocket長(zhǎng)連接以及其不確定因素,輪詢依然是相對(duì)比較合適的方案;
Websocket各瀏覽器的支持情況:
https://caniuse.com/#search=websocket?
作業(yè):實(shí)現(xiàn)秒殺成功后給頁面推送秒殺結(jié)果;
注冊(cè)Servlets, Filters, Listeners作為Spring Beans
使用嵌入式Servlet容器時(shí),可以通過使用Spring Bean或掃描Servlet組件來從Servlet規(guī)范中注冊(cè)Servlet,過濾器和所有監(jiān)聽器(例HttpSessionListener);

使用@ServletComponentScan啟用自動(dòng)注冊(cè)帶有@ WebServlet,@ WebFilter和@WebListener的類;
默認(rèn)情況下,如果上下文僅包含單個(gè)Servlet,則將其映射到/,對(duì)于多個(gè)servlet bean,bean名稱用作路徑前綴;
如果基于約定的映射不夠靈活,則可以使用ServletRegistrationBean,F(xiàn)ilterRegistrationBean和ServletListenerRegistrationBean類進(jìn)行完全控制;
具體參考代碼和視頻演示;
SpringBoot使用攔截器
1、按照Spring mvc的方式編寫一個(gè)攔截器類;
2、編寫一個(gè)配置類implements WebMvcConfigurer接口
3、為該配置類添加@Configuration注解,標(biāo)注此類為一個(gè)配置類,讓Spring boot 掃描到;
4、覆蓋其中的方法并添加已經(jīng)編寫好的攔截器:

SpringBoot內(nèi)嵌Web服務(wù)器
Spring Boot 默認(rèn)是使用Tomcat 來作為內(nèi)嵌的Servlet 容器運(yùn)行我們的web程序,我們也可以將Servlet容器切換為其他服務(wù)器,比如Undertow?、Jetty服務(wù)器,只需要通過pom.xml文件中配置即可;
Undertow?是什么?
在早些年,有一款基于 Java EE 的免費(fèi)開源的應(yīng)用服務(wù)器JBoss (也叫JBoss AS) ,由 JBoss 社區(qū)維護(hù)(另外注意 JBoss 旗下還有另一款商用應(yīng)用服務(wù) JBoss EAP,由Radhat提供商業(yè)支持);
JBoss 服務(wù)器的核心服務(wù)僅支持 EJB,不支持 JSP 和 Servelt,所以 JBoss 之前一直在內(nèi)部綁定 Tomcat 作為 Web 容器,但后來JBoss不想一直綁定tomcat作為web容器,所以到 JBoss 8.0(改名叫 wildfly)的版本后,JBoss 終于有了一款屬于自己的 Web 容器“Undertow”;
JBoss(內(nèi)嵌Tomcat) -->?wildfly(內(nèi)嵌Undertow)
JBoss 8.0(改名叫wildfly)?https://wildfly.org?(內(nèi)嵌 http://undertow.io)
認(rèn)識(shí)一下Jetty?
Jetty 是一款由Eclipse開源的Servlet容器,為JSP和servlet提供運(yùn)行環(huán)境,Jetty是使用Java語言編寫的;
https://www.eclipse.org/jetty/?
SpringBoot使用Undertow?或Jetty?服務(wù)器,修改pom文件:
1、排除掉Tomcat:

2、添加undertow或者jetty的依賴;

啟動(dòng)日志:
Undertow started on port(s) 8090 (http) with context path '/24-springboot'
注意:undertow不支持JSP;

https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/reference/html/spring-boot-features.html#boot-features-jsp-limitations?

啟動(dòng)日志:
Jetty started on port(s) 8090 (http/1.1) with context path '/25-springboot'
Jetty要支持JSP,需再添加幾個(gè)依賴:

重新啟動(dòng)后根據(jù)控制臺(tái)輸出的日志發(fā)現(xiàn)容器已經(jīng)切換成undertow、jetty;
當(dāng)運(yùn)行使用嵌入式Servlet容器的Spring Boot應(yīng)用程序時(shí),JSP支持存在一些限制;
使用java -jar運(yùn)行時(shí)候,可能會(huì)出現(xiàn)不支持JSP;
像Undertow就完全不支持JSP;
SpringBoot打包部署
打war包
1. 程序入口類需擴(kuò)展繼承 SpringBootServletInitializer 類
2、程序入口類覆蓋如下方法:

3、更新包為war,在 pom.xml 中修改 <packaging>war</packaging>
4、配置springboot打包的插件

注意pom.xml文件添加build信息:(避免一些資源沒有打到包里面去)

1、在項(xiàng)目中通過 Maven ?package 命令打一個(gè)war包,然后將war包部署到tomcat下運(yùn)行;
打jar包
對(duì)Jsp的支持有一些限制,打的jar不支持jsp訪問;
1、Spring boot程序打jar包,在pom.xml文件加入如下Spring boot的maven插件:

上面這個(gè)插件打jar包請(qǐng)使用1.4.2版本,其他版本有點(diǎn)問題,就是jsp無法訪問)
2、在項(xiàng)目中使用 Maven package命令打一個(gè)jar包;
3、使用java -jar 運(yùn)行第2步生成的jar包,從而可以啟動(dòng) Spring boot 程序;
4、訪問第3步運(yùn)行起來的 spring boot程序;
如果想更深入的學(xué)習(xí)springboot,奉上springboot全套視頻教程,視頻學(xué)習(xí)效果更佳,走過路過別忘素質(zhì)三連哦~~

