首先 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\index.html
<!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">
<h2>WebSocket Test Page</h2>
<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" 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 进行前后端的通信了,如果大家还有不明白的或者有更好的方法,可以在下方的留言区讨论。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。