乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      springBoot 整合websocket

       jackeyqing 2019-04-07

      前言:最近開(kāi)發(fā)公司的一個(gè)會(huì)員卡,酒店預(yù)訂房間的功能,考慮到要實(shí)現(xiàn)后臺(tái)管理的訂單提示,所以在項(xiàng)目中引用websocket,事實(shí)上在spring boot中引入webSocket 還是非常簡(jiǎn)單的,但是我還是爬了很多坑,在此記錄一下希望可以幫助一些可能同樣會(huì)爬坑的同學(xué)。

      1:jar包的引入,只引這個(gè)的前提是使用tomcat7.0以上的版本,我用的是tomcat8,所以用這個(gè)就夠了,若是低版本的還需引入javaee-api。

      1. <dependency>
      2. <groupId>org.springframework.boot</groupId>
      3. <artifactId>spring-boot-starter-websocket</artifactId>
      4. </dependency>

      2:配置文件,這里要注意一下,使用springboot的內(nèi)置tomcat運(yùn)行和打war包發(fā)布到外部Tomcat運(yùn)行時(shí)配置是不一樣的。

        1.先創(chuàng)建一個(gè)WebSocketConfig.java

         2.使用spring boot內(nèi)置tomcat運(yùn)行時(shí)的配置。

      1. import org.springframework.context.annotation.Bean;
      2. import org.springframework.stereotype.Component;
      3. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
      4. @Component
      5. public class WebSocketConfig {
      6. @Bean
      7. public ServerEndpointExporter serverEndpointExporter(){
      8. return new ServerEndpointExporter();
      9. }
      10. }

       這里的配置是ServerEndpointExporter的注入,配置該出會(huì)為我們后面使用到@ServerEndPoint注解的地方自動(dòng)注冊(cè)Websocket endpoint。

       3.使用外部的tomcat發(fā)布時(shí) WebSocketConfig.java 中就不需要 ServerEndpointExporter 的注入,因?yàn)檫@是它是由外部容器自己提供和管理的,如果你在使用外部容器發(fā)布時(shí)注入這個(gè)bean,項(xiàng)目啟動(dòng)的時(shí)候會(huì)報(bào) javax.websocket.DeploymentException: Multiple Endpoints may not be deployed to the same path xxxx錯(cuò)誤,別問(wèn)我是怎么知道的(/"≡ _ ≡)/~┴┴。

      所以這個(gè)時(shí)候的配置是這樣的:

      1. import org.springframework.context.annotation.Bean;
      2. import org.springframework.stereotype.Component;
      3. import org.springframework.web.socket.server.standard.ServerEndpointExporter;
      4. @Component
      5. public class WebSocketConfig {
      6. // @Bean
      7. // public ServerEndpointExporter serverEndpointExporter(){
      8. // return new ServerEndpointExporter();
      9. // }
      10. }

      3:上面都配置好后我們就來(lái)看websocket使用的重頭戲@ServerEndpoint的使用,前面有說(shuō)。之前的配置就是為了是項(xiàng)目能在使用了注解的地方自動(dòng)注冊(cè)Websocket endpoint,在這里我們就能實(shí)現(xiàn)websocket的鏈接、關(guān)閉、發(fā)送和接收消息的操作,這文件看起來(lái)有點(diǎn)像controller,但又有些不同,所以我就把他放在service層了這個(gè)有參考慕課網(wǎng)廖師兄的操作。

      1.創(chuàng)建一個(gè)WebSocket.java。

      1. import lombok.extern.slf4j.Slf4j;
      2. import org.springframework.stereotype.Component;
      3. import javax.websocket.OnClose;
      4. import javax.websocket.OnMessage;
      5. import javax.websocket.OnOpen;
      6. import javax.websocket.Session;
      7. import javax.websocket.server.ServerEndpoint;
      8. import java.util.concurrent.CopyOnWriteArraySet;
      9. @Component
      10. @ServerEndpoint(value = "/webSocket")
      11. @Slf4j
      12. public class WebSocket {
      13. private Session session;
      14. private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();
      15. @OnOpen
      16. public void onOpen(Session session){
      17. this.session = session;
      18. webSocketSet.add(this);
      19. log.info("[WebSocket消息]有新的連接,總數(shù):{}", webSocketSet.size());
      20. }
      21. @OnClose
      22. public void onClose(Session session){
      23. webSocketSet.remove(this);
      24. log.info("[WebSocket消息]連接斷開(kāi),總數(shù):{}", webSocketSet.size());
      25. }
      26. @OnMessage
      27. public void onMessage(String message){
      28. if("123456789".equals(message)){
      29. sendMessage(message);
      30. }
      31. log.info("[WebSocket消息]接收到客戶(hù)端的消息:{}", message);
      32. }
      33. public void sendMessage(String message){
      34. for (WebSocket webSocket:webSocketSet){
      35. log.info("【websocket消息】廣播消息,message=:{}",message );
      36. try {
      37. webSocket.session.getBasicRemote().sendText(message);
      38. }catch (Exception e){
      39. e.printStackTrace();
      40. }
      41. }
      42. }
      43. }
      其實(shí)看注解名字也能猜到各個(gè)方法的操作的是什么。

      @OnOpen:在前端訪(fǎng)問(wèn)websocket時(shí)開(kāi)一個(gè)新的連接。這里有用一個(gè)集合來(lái)記錄連接,方便查看管理;

      @OnClose:斷開(kāi)連接;

      @OnMessage:接收消息接口;

      sendMessage:發(fā)送消息的接口;

      到目前為止服務(wù)端的準(zhǔn)備就做好了。

      現(xiàn)在開(kāi)始前端調(diào)用,這里使用的是原生Html5來(lái)調(diào)用如下:

      1. <script>
      2. var lockReconnect = false;//避免重復(fù)連接
      3. var wsUrl = "ws://localhost:8008/webSocketTest/webSocket";
      4. var ws;
      5. var tt;
      6. createWebSocket();
      7. function createWebSocket() {
      8. try {
      9. ws = new WebSocket(wsUrl);
      10. init();
      11. } catch(e) {
      12. console.log('catch'+e);
      13. reconnect(wsUrl);
      14. }
      15. }
      16. function init() {
      17. ws.onclose = function () {
      18. console.log('鏈接關(guān)閉');
      19. reconnect(wsUrl);
      20. };
      21. ws.onerror = function() {
      22. console.log('發(fā)生異常了');
      23. reconnect(wsUrl);
      24. };
      25. ws.onopen = function () {
      26. console.log('建立連接');
      27. //心跳檢測(cè)重置
      28. heartCheck.start();
      29. };
      30. ws.onmessage = function (event) {
      31. console.log('接收到消息');
      32. if(event.data!="123456789"){
      33. console.log('收到消息:'+event.data);
      34. //彈窗提醒, 播放音樂(lè)
      35. $('#myModal').modal('show');
      36. document.getElementById('notice').play();
      37. }
      38. heartCheck.start();
      39. //拿到任何消息都說(shuō)明當(dāng)前連接是正常的
      40. }
      41. }
      42. window.onbeforeunload = function () {
      43. ws.close();
      44. }
      45. var lockReconnect = false;//避免重復(fù)連接
      46. function reconnect(url) {
      47. if(lockReconnect) {
      48. return;
      49. };
      50. lockReconnect = true;
      51. //沒(méi)連接上會(huì)一直重連,設(shè)置延遲避免請(qǐng)求過(guò)多
      52. tt && clearTimeout(tt);
      53. tt = setTimeout(function () {
      54. createWebSocket(url);
      55. lockReconnect = false;
      56. }, 4000);
      57. }
      58. //心跳檢測(cè)
      59. var heartCheck = {
      60. timeout: 60000,
      61. timeoutObj: null,
      62. serverTimeoutObj: null,
      63. start: function(){
      64. console.log('start');
      65. var self = this;
      66. this.timeoutObj && clearTimeout(this.timeoutObj);
      67. this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
      68. this.timeoutObj = setTimeout(function(){
      69. //這里發(fā)送一個(gè)心跳,后端收到后,返回一個(gè)心跳消息,
      70. //onmessage拿到返回的心跳就說(shuō)明連接正常
      71. console.log('55555');
      72. ws.send("123456789");
      73. self.serverTimeoutObj = setTimeout(function() {
      74. console.log(111);
      75. console.log(ws);
      76. ws.close();
      77. // createWebSocket();
      78. }, self.timeout);
      79. }, this.timeout)
      80. }
      81. }
      82. </script>

      其實(shí)這里和上面ServerEndpoint一樣,想必大家也是見(jiàn)文知意。

      無(wú)非是初始化一個(gè)Websocket,創(chuàng)建連接,關(guān)閉連接,接收消息,發(fā)送消息,這些就不多說(shuō)了,主要在這里說(shuō)一下幾個(gè)需要注意的點(diǎn)。

      1:初始化時(shí) new WebSocket(wsUrl );  這個(gè)url就是請(qǐng)求連接@ServerEndpoint配置的地方,所以說(shuō)它的使用時(shí)候是不是有點(diǎn)像Controller的使用,拿上面的請(qǐng)求路徑做個(gè)說(shuō)明:

      var wsUrl = "ws://localhost:8008/webSocketTest/webSocket";

      ws:是websocket的協(xié)議,websocket用的不是http協(xié)議,這里我就不對(duì)這兩個(gè)協(xié)議的區(qū)別做詳細(xì)的說(shuō)明,有興趣自己搜一下。需要注意的是如果請(qǐng)求頭的是http的就用ws,若請(qǐng)求的是https則使用wss。

      localhost:就是服務(wù)的ip或域名。

      8008:端口號(hào)。

      webSocketTest:發(fā)布的項(xiàng)目名。

      webSocket:@ServerEndpoint中配置的路徑。

      2.websocket長(zhǎng)連接有默認(rèn)的超時(shí)時(shí)間(proxy_read_timeout),就是超過(guò)一定的時(shí)間沒(méi)有發(fā)送任何消息,連接會(huì)自動(dòng)斷開(kāi)。所以我們要想保持長(zhǎng)連接可以使用心跳包,定時(shí)像服務(wù)器發(fā)送心跳保持通信,上面的js中就有使用,當(dāng)發(fā)生錯(cuò)誤或斷開(kāi)連接時(shí)我們可以重新連接。

      3.最后再提醒一下,如果項(xiàng)目部署到線(xiàn)上是使用了Nginx代理,一定要記得在Nginx配置websocket,前面有說(shuō)過(guò)wesocket使用的不是http協(xié)議,如果你用了Nginx又沒(méi)有配置websocket的話(huà),前端初始化websocket就會(huì)報(bào)404。

      下面引用其他博主的一個(gè)解決方案,具體參考:springboot + websocket + linux服務(wù)器(nginx)404問(wèn)題解決

      配置nginx反向代理響應(yīng)webSocket請(qǐng)求 需要在代理的請(qǐng)求配置中加入下面的配置:

      1. proxy_set_header Upgrade $http_upgrade;
      2. proxy_set_header Connection "upgrade";1

       Nginx配置

      1. server {
      2. listen 80;
      3. server_name localhost;
      4. #charset koi8-r;
      5. location / {
      6. root /usr/java/myproject/sell;
      7. index index.html index.htm;
      8. }
      9. location /sell/ {
      10. proxy_pass http://127.0.0.1:8081/sell/;
      11. }
      12. location /sell/webSocket {
      13. proxy_pass http://127.0.0.1:8081/sell/webSocket;
      14. proxy_set_header Upgrade $http_upgrade;
      15. proxy_set_header Connection "upgrade";
      16. }
       
       

       

       

       

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多