文章目录
1.什么是websocket协议?
WebSocket是HTML5中的协议, 他是为了解决客户端发起多个http请求到服务器资源浏览器必须要经过长时间的轮训问题而生的,他实现了多路复用,他是全双工通信。在webSocket协议下客服端和浏览器可以同时发送信息。
2.与http协议的不同
区别 | http | websocket |
---|---|---|
链接方式 | http1.0即普通http请求,一般都是短链接,一次请求,三次握手,完毕之后立即断开 | 其实websocket是http协议的升级,http1.1版本默认长链接,长链接代表:一次链接,在一定限期内保持着链接,保持tcp不断开,双方都可以即时通讯,是一种全双工通信协议 |
场景 | http协议更适合普通文件请求,不适合即时通讯,一般我们要得到及时信息,通过http方式,我们就需要不断的轮询,网络资源消耗大 | websocket更适合做即及时通讯,不需要不断的轮询,一次链接,长时间有效 |
3.代码实现
3.1导入pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
</parent>
<groupId>com.liuhao.springboot</groupId>
<artifactId>springboot-websocket</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-websocket</name>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- websocket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>
3.2编写websocketCofig类
package com.liuhao.application.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
/**
* @return
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
3.3实现websocket协议类
package com.liuhao.application.pojo;
import java.io.IOException;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;
@ServerEndpoint("/websocket/{sid}")
@Component
public class WebSocketServer {
// session 会话集合
private static ConcurrentHashMap<String, Session> map = new ConcurrentHashMap<String, Session>();
// 当前会话
private Session session;
// sid
private String sid = "";
/**
* 连接
*
* @param session 服务器与客户端建立建立连接,生成会话
* @param sid 客户端的唯一id
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
this.session = session;
this.sid = sid;
System.out.println("有一个连接sid:" + this.sid);
this.map.put(this.sid, this.session);
}
/**
* 关闭当前会话
*/
@OnClose
public void onClose() {
try {
// 从名单中清楚
this.map.remove(this.sid);
// 关闭会话
this.session.close();
System.out.println("sid:" + sid + "会话被关闭,移除");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 接受消息
*
* @param message 接受到的消息
*/
@OnMessage
public void onMessage(String message) {
try {
System.out.println("message:" + message);
// 广播消息
for (Entry<String, Session> entry : map.entrySet()) {
entry.getValue().getBasicRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 发送消息
*
* @param massage 需要发送消息
*/
public void sendMassage(String massage) {
try {
this.session.getBasicRemote().sendText(massage);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.4前端页面
<!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">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap 101 Template</title>
<link rel="stylesheet" type="text/css" href="../css/bootstrap.css" />
<script src="../js/Vue2.6.11.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div class="container">
<form action="" method="">
<div class="row">
<div class="form-group col-md-6">
<label>信息展示:</label>
<textarea class="form-control" rows="10" cols="" v-model="showContent"></textarea>
</div>
<div class="col-md-6">
<div class="row">
<div class="form-group col-md-12">
<label>发送人ID:</label>
<input type="text" class="form-control" name="" v-model="id" />
</div>
</div>
<div class="row">
<div class="form-group col-md-12">
<label>发送信息:</label>
<textarea class="form-control" rows="6" cols="" v-model="sendContent"></textarea>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<button type="button" class="btn btn-primary btn-block" @click="sendMsg()">点击发送</button>
</div>
<div class="form-group col-md-6">
<button type="button" class="btn btn-danger btn-block" @click="connect()">连接</button>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
id: '',
showContent: '',
sendContent: '',
socket: null
},
methods: {
connect: function() {
var lsocket;
if (typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket,请更换浏览器");
return;
} else {
console.log("您的浏览器支持WebSocket");
if (this.id.trim() == "") {
alert('连接之前必须指定唯一ID')
return
}
lsocket = new WebSocket("ws://localhost:8080/websocket/" + this.id)
this.socket = lsocket
this.socket.onopen = function() {
console.log('连接已开放')
}
this.socket.onerror = function() {
alert('websocket出现error')
}
this.socket.onmessage = function(msg) {
console.log(msg)
vm.showContent += msg.data
}
}
},
sendMsg: function() {
if(this.sendContent.trim()==""||this.socket==null)
{
alert('不能发送空的信息哦,发送信息前,要先连接')
return
}
this.socket.send(this.sendContent)
this.sendContent=''
}
},
created: function() {
}
})
</script>
</body>
</html>
3.5App启动类
package com.liuhao.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}