当前位置: 移动技术网 > IT编程>开发语言>Java > Java中Spring WebSocket详解

Java中Spring WebSocket详解

2019年07月19日  | 移动技术网IT编程  | 我要评论

首先 pom.xml

<parent>
	<groupid>org.springframework.boot</groupid>
	<artifactid>spring-boot-starter-parent</artifactid>
	<version>1.5.8.release</version>
</parent>
<dependency>
	<groupid>org.apache.commons</groupid>
	<artifactid>commons-io</artifactid>
</dependency>
<dependency>
	<groupid>javax.websocket</groupid>
	<artifactid>javax.websocket-api</artifactid>
	<version>1.0</version>
	<scope>provided</scope>
</dependency>
<dependency>
	<groupid>org.springframework</groupid>
	<artifactid>spring-websocket</artifactid>
</dependency>
<dependency>
	<groupid>org.springframework.boot</groupid>
	<artifactid>spring-boot-starter-web</artifactid>
	<exclusions>
		<exclusion>
			<groupid>org.springframework.boot</groupid>
			<artifactid>spring-boot-starter-tomcat</artifactid>
		</exclusion>
	</exclusions>
</dependency>
<dependency>
	<groupid>org.springframework.boot</groupid>
	<artifactid>spring-boot-starter-undertow</artifactid>
</dependency>

接收消息后的处理类 gamehandler :

import java.net.uri;
import org.springframework.web.socket.binarymessage;
import org.springframework.web.socket.closestatus;
import org.springframework.web.socket.pongmessage;
import org.springframework.web.socket.textmessage;
import org.springframework.web.socket.websocketsession;
import org.springframework.web.socket.handler.abstractwebsockethandler;

public class gamehandler extends abstractwebsockethandler {
 /**
  * 处理字符串类的信息
  *
  * @param session
  * @param message
  * @throws exception
  */
 @override
 protected void handletextmessage(websocketsession session, textmessage message) throws exception {
  session.sendmessage(new textmessage(message.asbytes()));
 }

 /**
  * 处理二进制类的信息
  *
  * @param session
  * @param message
  * @throws exception
  */
 @override
 protected void handlebinarymessage(websocketsession session, binarymessage message) throws exception {
  session.sendmessage(new binarymessage(message.getpayload()));
 }

 /**
  * ping-pong
  *
  * @param session
  * @param message
  * @throws exception
  */
 @override
 protected void handlepongmessage(websocketsession session, pongmessage message) throws exception {
	
 }
 /**
  * 传出错误的处理
  *
  * @param session
  * @param exception
  * @throws exception
  */
 @override
 public void handletransporterror(websocketsession session, throwable exception) throws exception {
 }
 /**
  * 连接关闭的处理
  *
  * @param session
  * @param status
  * @throws exception
  */
 @override
 public void afterconnectionclosed(websocketsession session, closestatus status) throws exception {
 }
 /**
  * 连接建立后的处理
  *
  * @param session
  * @throws exception
  */
 @override
 public void afterconnectionestablished(websocketsession session) throws exception {	
 }
}

 握手信息拦截器 websockethandshakeinterceptor :

import java.util.map;
import javax.servlet.http.cookie;
import org.springframework.http.server.serverhttprequest;
import org.springframework.http.server.serverhttpresponse;
import org.springframework.http.server.servletserverhttprequest;
import org.springframework.web.socket.websockethandler;
import org.springframework.web.socket.server.handshakeinterceptor;

public class websockethandshakeinterceptor implements handshakeinterceptor {
 @override
 public boolean beforehandshake(serverhttprequest request, serverhttpresponse shr1, websockethandler wsh, map<string, object> attributes) throws exception {
  // 此处可以做一些权限认证的事情或者其他
  return true;
 }
 @override
 public void afterhandshake(serverhttprequest shr, serverhttpresponse shr1, websockethandler wsh, exception excptn) {	
 }
}

使用websocket的配置类 websocketconfig :

import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter;
import org.springframework.web.socket.config.annotation.enablewebsocket;
import org.springframework.web.socket.config.annotation.websocketconfigurer;
import org.springframework.web.socket.config.annotation.websockethandlerregistry;

@configuration
@enablewebsocket
public class websocketconfig extends webmvcconfigureradapter implements websocketconfigurer {
@override
 public void registerwebsockethandlers(websockethandlerregistry registry) {
  // 允许连接的域,只能以http或https开头
  string[] allowsorigins = {"http://127.0.0.1:1213", "http://localhost:1213"};
  registry.addhandler(gamehandler(),"/game").addinterceptors(handshakeinterceptor()).setallowedorigins(allowsorigins);
 }
 @bean
 public gamehandler gamehandler() {
  return new gamehandler();
 }
 @bean
 public websockethandshakeinterceptor handshakeinterceptor() {
  return new websockethandshakeinterceptor();
 }
}

启动类 launcher :

@springbootapplication
public class launcher {
 public static void main(string[] params) {
  springapplication.run(launcher.class, params);
	}
}

配置文件 main/resources/application.properties:

server.port=1213
server.session-timeout=1800
server.undertow.io-threads=4
server.undertow.worker-threads=20
server.undertow.buffer-size=1024
server.undertow.buffers-per-region=1024
server.undertow.direct-buffers=true

前端的测试页面 main\resources\static\

<!doctype html>
<html lang="zh-cn">
 <head>
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>platform gateway</title>
  <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="external nofollow" rel="stylesheet">
  <!--<link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" rel="external nofollow" rel="stylesheet">-->
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdn.bootcss.com/jquery-scrollto/2.1.2/jquery.scrollto.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pako/1.0.6/pako.min.js"></script>
  <!--[if lt ie 9]>
   <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
   <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
  <![endif]-->
  <style>
   #message{
    height: 600px;
    overflow-y:auto;
   }
  </style>
 </head>
 <body>
  <div class="container">
   <h1>websocket test page</h1>
   <hr/>
   <div class="form-inline">
    <div class="form-group">
     <label for="wsaddr">websocket address: </label>
     <div class="input-group">
      <span class="input-group-addon" id="basic-ws">ws://127.0.0.1:1213/</span>
      <input type="text" class="form-control" id="basic-ws-addr" aria-describedby="basic-ws" placeholder="game" data-container="body" data-placement="top" data-content="链接地址不能为空,请填写">
     </div>
    </div>
    <button type="button" id="btnconnect" class="btn btn-primary" onclick="connect();">
     <span class="glyphicon glyphicon-resize-small" aria-hidden="true"></span>
     连接
    </button>
    <button type="button" id="btnclose" class="btn btn-danger" disabled="disabled" onclick="closewebsocket();">
     <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
     断开
    </button>
    <button type="button" id="btnsend" class="btn btn-info" disabled="disabled" style="margin-left: 50px;" onclick="send();">
     <span class="glyphicon glyphicon-transfer" aria-hidden="true"></span>
     发送消息
    </button>
   </div><br/>
   <textarea class="form-control" id="inmsg" rows="5" placeholder="在这里输入需要发送的信息..."></textarea>
   <hr/>
   <div id="message"></div>
  </div>
  <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
  <script type="text/javascript">
     function zip(str) {
      var binarystring = pako.gzip(str, {to: 'string'});
      return btoa(binarystring);
     }
     function unzip(b64data) {
      var strdata = atob(b64data);
      var chardata = strdata.split('').map(function (x) {
       return x.charcodeat(0);
      });
      var bindata = new uint8array(chardata);
      var data = pako.inflate(bindata);
      strdata = string.fromcharcode.apply(null, new uint16array(data));
      return strdata;
     }
     var websocket = null;
     var wsbaseurl = null;
     var wsurl = null;
     function init() {
      wsbaseurl = "ws://" + window.location.host + "/";
      $("#basic-ws").text(wsbaseurl);
      $(function () {
       $('[data-toggle="popover"]').popover();
      });
      return false;
     }
//关闭websocket连接
     function closewebsocket() {
      if (websocket) {
       websocket.close();
      }
      return false;
     }

//将消息显示在网页上
     function setmessageinnerhtml(who, msg) {
      var message = null;
      if (who === 1) {
       message = '<div class="alert alert-success" role="alert">本地: ' + msg + '</div>';
      } else {
       message = '<div class="alert alert-info" role="alert">服务器: ' + msg + '</div>';
      }
      document.getelementbyid('message').innerhtml = (document.getelementbyid('message').innerhtml + message);
      $("#message").scrollto('100%');
      return false;
     }

//发送消息
     function send() {
      if (websocket) {
       var message = $("#inmsg").val();
       websocket.send(zip(message));
       setmessageinnerhtml(1, message);
      }
      return false;
     }
     function connect() {
      var url = $("#basic-ws-addr").val();
      if (url.length <= 0) {
       $('#basic-ws-addr').popover('show');
       settimeout(function () {
        $('#basic-ws-addr').popover('hide');
       }, 3000);
      } else {
       wsurl = wsbaseurl + url;
       if ('websocket' in window) {
        websocket = new websocket(wsurl);
        //连接发生错误的回调方法
        websocket.onerror = function () {
         setmessageinnerhtml(0, "websocket连接发生错误 -> " + wsurl);
         $("#btnconnect").removeattr("disabled");
         $("#btnclose").attr("disabled", "disabled");
         $("#btnsend").attr("disabled", "disabled");
        };

        //连接成功建立的回调方法
        websocket.onopen = function () {
         setmessageinnerhtml(0, "websocket连接成功 -> " + wsurl);
         $("#btnconnect").attr("disabled", "disabled");
         $("#btnclose").removeattr("disabled");
         $("#btnsend").removeattr("disabled");
        };

        //接收到消息的回调方法
        websocket.onmessage = function (event) {
         setmessageinnerhtml(0, unzip(event.data));
        };

        //连接关闭的回调方法
        websocket.onclose = function () {
         setmessageinnerhtml(0, "websocket连接关闭 -> " + wsurl);
         $("#btnconnect").removeattr("disabled");
         $("#btnclose").attr("disabled", "disabled");
         $("#btnsend").attr("disabled", "disabled");
        };

        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
         closewebsocket();
        };
       } else {
        alert('not support websocket');
       }
      }
      return false;
     }
     window.onload = init();
  </script>
 </body>
</html>

到此就可以使用 websocket 进行前后端的通信了,如果大家还有不明白的或者有更好的方法,可以在下方的留言区讨论。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网