websocket是客户端和服务端之间的通信,所以我们需要实现websocket的服务端和客户端,而这里客户端我们写到Html的前端中。websocket的开发需要进行以下几个步骤:
1.引入依赖<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
2.对websocket进行配置
@Component
public class WebSocketConfig {
//把你要实例化的对象转化成一个Bean,放在IoC容器中
@Bean
public ServerEndpointExporter serverEndpointExporter () {
return new ServerEndpointExporter();
}
}
注意:上面这种配置有个缺点,就是服务端的类里面无法使用@Value或@Autowired之类的Spring注入。修改的方法,痛过百度,在后面有写到。
3.编写服务端实现类。
websocket与普通controller不太一样,但也不是service。这里,笔者把它写在service目录下
该类应该有一下几个功能。@OnOpen有新的连接。@OnClose连接关闭。@OnMeesage收到信息。sendMessage发送信息。
package com.wechat.order.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
@Component
@ServerEndpoint("/webSocket")//调用websocket的url
@Slf4j
public class WebSocket {
private static int onlineCount = 0;//记录总连接数
//定义一个websocket的容器,用来储存这些session
private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<>();//注意这里不能直接使用Set集合。
private Session session;
/**
* 有新的连接
* @param session
* @throws IOException
*/
@OnOpen
public void onOpen(Session session) throws IOException{
this.session = session;
webSocketSet.add(this);
incrOnlineCount();//连接数+1
log.info("【websocket消息】有新的连接,当前总连接数: {}", getOnlineCount());
}
/**
* 连接关闭
* @throws IOException
*/
@OnClose
public void onClose() throws IOException{
webSocketSet.remove(this);
decOnlineCount();//连接数-1
log.info("【websocket消息】有连接断开,当前总连接数:: {}", getOnlineCount());
}
/**
* 收到信息
* @param message 收到的信息内容
* @param session
* @throws IOException
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
log.info("【websocket消息】收到客户端发来的消息: {}", message);
// broadcast received message
for(WebSocket item : webSocketSet){
item.sendMessage(message);
}
}
/**
* 使用广播发送消息
* @param message
*/
public void sendMessage(String message) {
log.info("【websocket消息】广播消息: {}", message);
for(WebSocket webSocket : webSocketSet){
//发送消息这类不是特别重要,不影响程序运行的异常可以直接try,catch
try {
webSocket.session.getBasicRemote().sendText(message);
}catch (Exception e) {
log.error("websocket消息】广播消息异常: {}", e.getStackTrace());
}
}
}
/**
* 当前连接数
* @return
*/
public static synchronized int getOnlineCount(){
return WebSocket.onlineCount;
}
/**
* 连接记录+1
*/
public static synchronized void incrOnlineCount(){
WebSocket.onlineCount++;
}
/**
* 连接记录-1
*/
public static synchronized void decOnlineCount(){
WebSocket.onlineCount--;
}
}
4.客户端,这里使用html的js和vue来实现
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>My WebSocket</title>
<script src="js/vue.js"></script>
</head>
<body>
Welcome To My WebSocket.<br/><br/>
<div id="ws">
<input id="text" type="text"/>
<button οnclick="sendMsg()">Send</button>
<button οnclick="closeWS()" :disabled="!opened">Close</button>
<button οnclick="openWS()" :disabled="opened">Open</button>
<div v-html="msg"></div>
</div>
</body>
<script type="text/javascript">
var websocket = null;
var wsVue = new Vue({
el: '#ws',
data: {
msg: "welcome to my websocket...<br/>",
opened: false
},
mounted: function(){
initWs();
}
});
function initWs() {
//check if your browser supports WebSocket
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/webSocket");
}
else {
alert('Sorry, websocket not supported by your browser.')
}
//Error callback
websocket.onerror = function () {
setMessageContent("error!");
wsVue.opened = false;
};
//socket opened callback
websocket.onopen = function (event) {
setMessageContent("websocket opened");
wsVue.opened = true;
}
//message received callback
websocket.onmessage = function (event) {
setMessageContent(event.data);
}
//socket closed callback
websocket.onclose = function () {
setMessageContent("websocket closed");
wsVue.opened = false;
}
//when browser window closed, close the socket, to prevent server exception
window.onbeforeunload = function () {
websocket.close();
}
}
//update message to vue and then in div
function setMessageContent(content) {
wsVue.msg += content + '<br/>';
}
//click to close the websocket
function closeWS() {
websocket.close();
wsVue.opened = false;
}
//click to open the websocket
function openWS() {
initWs();
}
//click to send message
function sendMsg() {
var message = document.getElementById('text').value;
websocket.send(message);
}
</script>
</body>
</html>
下面讲解配置websocket的第二种方法:
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(CmdHandler(), "/webSocket"); //url和handler的mapping
}
@Bean
public WebSocketHandler WebSocket() {
return new WebSocket();
}
}