springboot中WebSocket简单实现

一、原理: 

在未了解socket前一直以为javaweb项目就是通过前端页面触发事件后向后台请求,再通过后台响应给前端的一个过程。本来是这样的,但Websocket是可以Web浏览器和服务器之间进行任意的双向数据传输,是基于TCP协议实现,包含初始的握手过程,以及后续的多次数据帧双向传输过程。其目的是在WebSocket应用和WebSocket服务器进行频繁双向通信时,可以使服务器避免打开多个HTTP连接进行工作来节约资源,提高了工作效率和资源利用率。

当然不用websocket也可以实现从后台向前端发送信息的功能,比如用前端轮巡的方式(setInterval("function(){请求后台代码}",1000) 也可以实现,但这样正如上述所说的,给浏览器以及后台包括数据库访问都带来一定的压力,所以,采用更好的技术。

二、pom引用:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

三、后台代码:

@Component
@ServerEndpoint(value = "/websocket")
public class WebSocketTest {
	private static int onlineCount = 0;
	private static CopyOnWriteArrayList<WebSocketTest> webSocketSet = new CopyOnWriteArrayList<WebSocketTest>();
	private Session session;

	public WebSocketTest() {
		System.out.println("WebSocketTest.WebSocketTest()");
		System.out.println(this);
	}
	
	@OnOpen
	public void onOpen(Session session) {
		System.out.println("WebSocketTest.onOpen()");
		this.session = session;
		webSocketSet.add(this);// 加入set中
		addOnlineCount();
		System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
	}

	@OnClose
	public void onClose() {
		System.out.println("WebSocketTest.onClose()");
		System.out.println(this);
		webSocketSet.remove(this);
		subOnlineCount();
		System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
	}

	@OnMessage
	public void onMessage(String message, Session session) {
		System.out.println("WebSocketTest.onMessage()");
		System.out.println("来自客户端的消息:" + message);
		// 群发消息
		for (WebSocketTest item : webSocketSet) {
			try {
				System.out.println(item);
				item.sendMessage(message);
			} catch (IOException e) {
				e.printStackTrace();
				continue;
			}
		}
	}

	@OnError
	public void onError(Session session, Throwable throwable) {
		System.out.println("发生错误!");
		System.out.println("WebSocketTest.onError()");
		throwable.printStackTrace();
	}

	// 下面是自定义的一些方法
	public void sendMessage(String message) throws IOException {
		System.out.println("WebSocketTest.sendMessage()");
		System.out.println(this);
		this.session.getBasicRemote().sendText(message);
	}

	public static synchronized int getOnlineCount() {
		return onlineCount;
	}

	public static synchronized void addOnlineCount() {
		WebSocketTest.onlineCount++;
	}

	public static synchronized void subOnlineCount() {
		WebSocketTest.onlineCount--;
	}

	public static CopyOnWriteArrayList<WebSocketTest> getWebSocketSet() {
		return webSocketSet;
	}

	public static void setWebSocketSet(CopyOnWriteArrayList<WebSocketTest> webSocketSet) {
		WebSocketTest.webSocketSet = webSocketSet;
	}

这里记得,在添加一个配置类:注入ServerEndpointExporter对象Bean到容器

@Configuration
public class WebSocketConfig {

   @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }

}

前端代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- <script type="text/javascript" src="jquery-2.2.4.js"></script> -->
</head>
<body>
Welcome<br/><input id="text" type="text"/>
<button onclick="send()">发送消息</button>
<hr/>
<button onclick="closeWebSocket()">关闭WebSocket连接</button>
<hr/>
<div id="message"></div>
</body>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否支持WebSocket
var prefix = ((window.location.protocol === "https:") ? "wss://" : "ws://") + window.location.host + "/websocket";
if ('WebSocket' in window) {
	websocket = new WebSocket(prefix);
}else if ('MozWebSocket' in window) {
	websocket = new WebSocket(prefix);
}else {
	websocket = new SockJS(prefix);
}


//连接发生错误的回调方法
websocket.onerror = function () {
    setMessageInnerHTML("WebSocket连接发生错误");
};

//连接成功建立的回调方法
websocket.onopen = function () {
    setMessageInnerHTML("WebSocket连接成功");
}

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

//连接关闭的回调方法
websocket.onclose = function () {
    setMessageInnerHTML("WebSocket连接关闭");
}

//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
    closeWebSocket();
}

//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
    document.getElementById('message').innerHTML += innerHTML + '<br/>';
}

//关闭WebSocket连接
function closeWebSocket() {
    websocket.close();
}

//发送消息
function send() {
    var message = document.getElementById('text').value;
    websocket.send(message);
}

</script>
</html>

这里就可以运行了,看看效果,在运行成功之前遇到了两个问题,其中一个是前端报错:

failed: Error during WebSocket handshake: Unexpected response code: 404

最后发现是配置类没有被注入到容器里面,可以用@Configuration,或者是websocket所在的类没有被注入到容器中,加@Component就可以了,因为@ServerEndpoint不会被容器当成一个对象注入的。

当然在解决问题之前,网上搜的相关异常解决问题各有所获,但并不能解决问题,最多的是版本问题,这里提供一下我的springboot版本,和jdk版本作为参考

如果有用请点赞,如果有更好的意见,谢谢你的留言。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焱墩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值