阅读完需:约 5 分钟
WebSocket为浏览器和服务器之间提供了双工异步通信功能,也就是说我们可以利用浏览器给服务器发送消息,服务器也可以给浏览器发送消息,目前主流浏览器的主流版本对WebSocket的支持都算是比较好的,但是在实际开发中使用WebSocket工作量会略大,而且增加了浏览器的兼容问题,这种时候我们更多的是使用WebSocket的一个子协议stomp,利用它来快速实现我们的功能。
1.首先创建一个项目:
总目录:
依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
尽管这里SpringBoot依赖是1.4,但是2.X的SpringBoot应该也差不多
2.配置 WebSocket
WebSocketConfig:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
//注册连接点
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
}
1.@EnableWebSocketMessageBroker
注解表示开启使用STOMP协议来传输基于代理的消息,Broker就是代理的意思。
2.registerStompEndpoints
方法表示注册STOMP协议的节点,并指定映射的URL。
3.registry.addEndpoint("/chat").withSockJS();
这一行代码用来注册STOMP协议节点,同时指定使用SockJS协议。
4.configureMessageBroker
方法用来配置消息代理,由于我们是实现推送功能,这里的消息代理是/topic
3.创建一个bean来存放
Message:
public class Message {
private String name;
private String content;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
4.创建控制器
HelloController:
@Controller
public class HelloController {
@MessageMapping("/hello") //接受游览器的消息
@SendTo("/topic/greetings") //消息转发
public Message greeting(Message message){
return message;
}//返回消息
}
关于这个控制器,首先@Controller注解不必多言,say方法上添加的@MessageMapping注解和我们之前使用的@RequestMapping类似。@SendTo
注解表示当服务器有消息需要推送的时候,会对订阅了@SendTo中路径的浏览器发送消息。
5.编写前端页面
这个案例需要三个js脚本文件,分别是STOMP协议的客户端脚本stomp.js、SockJS的客户端脚本sock.js以及jQuery
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="/webjars/jquery/jquery.min.js"></script>
<script src="/webjars/sockjs-client/sockjs.min.js"></script>
<script src="/webjars/stomp-websocket/stomp.min.js"></script>
</head>
<body>
<table>
<tr>
<td>请输入用户名</td>
<td><input type="text" id="name"></td>
</tr>
<tr>
<td><input type="button" id="connect" value="连接"></td>
<td><input type="button" id="disconnect" disabled="disabled" value="断开连接"></td>
</tr>
</table>
<div id="chat" style="display: none">
<table>
<tr>
<td>请输入聊天内容</td>
<td><input type="text" id="content"></td>
<td><input type="button" id="send" value="发送"></td>
</tr>
</table>
<div id="conversation">群聊进行中...</div>
</div>
<script>
$(function () {
$("#connect").click(function () {
connect();
})
$("#disconnect").click(function () {
if (stompClient!=null){
stompClient.disconnect();//若要从客户端主动断开连接,可调用 disconnect() 方法
}
setConnected(false);
})
$("#send").click(function () {
//JSON.stringify()的作用是将 JavaScript 对象转换为 JSON 字符串,而JSON.parse()可以将JSON字符串转为一个对象。
//send():连接成功后,客户端可使用 send() 方法向服务器发送信息
stompClient.send("/app/hello",{},JSON.stringify({'name':$("#name").val(),'content':$("#content").val()}));
})
})
var stompClient =null;
function connect() {
if(!$("#name").val()){ //没有名字就结束返回
return;
}
var socket=new SockJS('/chat');//URL需要连接的地址
stompClient=Stomp.over(socket); // 获取 STOMP 子协议的客户端对象
stompClient.connect({},function (success) { // 向服务器发起websocket连接并发送
setConnected(true);
//订阅、接收信息,必须先订阅相应的URL,即发送一个 SUBSCRIBE 帧,然后才能不断接收来自服务器的推送消息;
//订阅和接收消息通过 subscribe() 方法实现
stompClient.subscribe("/topic/greetings",function (msg) {
showGreeting(JSON.parse(msg.body));
});
})
}
//接收消息添加到页面
function showGreeting(msg) {
$("#conversation").append('<div>'+msg.name+':'+msg.content+'</div>')
}
function setConnected(flag) {
$("#connect").prop("disabled",flag);//prop() 方法设置或返回被选元素的属性和值。
$("#disconnect").prop("disabled",!flag);//取反
if(flag){
$("#chat").show();//显示可见
}else {
$("#chat").hide();//隐藏可见
}
}
</script>
</body>
</html>
关于前端的页面的 SockJS的客户端 :