# 简单体验 websocket 编程
# 1、前往 spring 官网下载 websocket 的例子
这一步就不细说了:https://github.com/spring-guides/gs-messaging-stomp-websocket.git
从 github 上把这个项目拉下来。
# 2、创建一个自己的 springboot 项目
这里你可以用 IDEA 脚手架帮你直接创建一个 springboot 项目,也可以自己手动创建。
创建完之后你的目录应该是下面这个样子。
# 3、拷贝静态文件
将例子中 static 文件夹下的文件拷贝到自己的 springboot 项目中来,具体如下图所示:
其中 bullet.html 是下一篇会用到的弹幕例子。可以先不管他!
# 4、引入依赖并且修改编写文件
# 1、引入 pom 依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.1.1-1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.14.graal</version>
</dependency>
</dependencies>
# 2、在 app 文件夹下建一个 class 文件 WebsocketConfig
import org.springframework.context.annotation.Configuration; | |
import org.springframework.messaging.simp.config.MessageBrokerRegistry; | |
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; | |
import org.springframework.web.socket.config.annotation.StompEndpointRegistry; | |
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; | |
@Configuration | |
@EnableWebSocketMessageBroker | |
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer { | |
@Override | |
public void registerStompEndpoints(StompEndpointRegistry registry) { | |
// registry.addEndpoint("/dreamlandWs").withSockJS(); | |
registry.addEndpoint("/dreamlandWs").setAllowedOrigins("*").withSockJS(); | |
} | |
@Override | |
public void configureMessageBroker(MessageBrokerRegistry registry) { | |
registry.enableSimpleBroker("/topic/","/user/"); | |
registry.setApplicationDestinationPrefixes("/dreamlandBullet"); | |
} | |
} |
解释:开启 websocket 通道,registerStompEndpoints 方法就是允许客户端向服务端注册 websocket 连接,addEndpoint 方法的作用是
限制连接的地址必须要携带你指定的路径,setAllowedOrigins 是设置域名,如果不设置可能会出现跨域问题,withSockJS 表示客户端用于连接
通道的方式。configureMessageBroker 方法是一些配置,enableSimpleBroker 是配置允许被订阅的通道,如果不配置这个客户端没法接收到
对应路径的消息,第二个 setApplicationDestinationPrefixes 是发送的通道路径。
# 3、在 web 文件夹下新建以下文件
BulletMessage
public class BulletMessage { | |
private String message; | |
private String videoId; | |
private String user; | |
private Long date; | |
public String getMessage() { | |
return message; | |
} | |
public void setMessage(String message) { | |
this.message = message; | |
} | |
public String getVideoId() { | |
return videoId; | |
} | |
public void setVideoId(String videoId) { | |
this.videoId = videoId; | |
} | |
public String getUser() { | |
return user; | |
} | |
public void setUser(String user) { | |
this.user = user; | |
} | |
public Long getDate() { | |
return date; | |
} | |
public void setDate(Long date) { | |
this.date = date; | |
} | |
} |
MessageController
import com.alibaba.fastjson.JSONObject; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.messaging.Message; | |
import org.springframework.messaging.handler.annotation.MessageMapping; | |
import org.springframework.messaging.simp.SimpMessagingTemplate; | |
import org.springframework.stereotype.Controller; | |
import org.springframework.web.bind.annotation.GetMapping; | |
@Controller | |
public class MessageController { | |
@Autowired | |
SimpMessagingTemplate simpMessagingTemplate; | |
// @SendTo("/topic/message") | |
@MessageMapping("/bullet") | |
public void broadCast(Message<Object> message) { | |
byte[] payload = (byte[]) message.getPayload(); | |
String content = new String(payload); | |
System.out.println(content); | |
JSONObject jsonObject = JSONObject.parseObject(content); | |
// return jsonObject.getString("bullet"); | |
serverSend(jsonObject.getString("bullet"), jsonObject.getString("videoId"), jsonObject.getString("user")); | |
} | |
@GetMapping("serverSend") | |
public void serverSend(String message, String id, String user) { | |
BulletMessage bulletMessage = new BulletMessage(); | |
bulletMessage.setMessage(message); | |
bulletMessage.setUser(user); | |
bulletMessage.setVideoId(id); | |
bulletMessage.setDate(System.currentTimeMillis()); | |
// simpMessagingTemplate.convertAndSend("/topic/message", message); | |
simpMessagingTemplate.convertAndSendToUser(id, "/bullet", bulletMessage); | |
} | |
} |
这里需要稍微解释一下:
BulletMessage
这个文件是弹幕的一个载体,用于服务器接收到客户端的弹幕后,组装成 BulletMessage 然后广播给所有订阅了对应地址的客户端。
MessageController
注解 @MessageMapping 指定了一个地址,之前配置了发送通道是 /dreamlandBullet , 发送地址就需要配合 @MessageMapping 进行
组装,也就是消息发送的地址是 /dreamlandBullet/bullet;@SendTo 配合的是客户端的订阅,客户端订阅了你 sendTo 指定的地址后,服务器会将消息广播到
所有订阅了 sendTo 指定地址的客户端。这个不符合我们视频弹幕多对多的要求,这里不讨论。为了实现动态指定推送,我们需要动态的配置发送地址,所以
有了 SimpMessagingTemplate
这个类。从发送过来的消息我们解析出一个规定的 id,这个 id 用于订阅地址的拼接,这样就能实现在指定 id 的视频发送
的弹幕只能在指定 id 视频弹幕列表中看到。
# 5、修改静态文件
这里就大概修改一下 app.js 就够了
首先是修改 sendName 方法,路径指定修改,然后消息体我们可以先写死。
function sendName() { | |
stompClient.send("/dreamlandBullet/bullet", {}, JSON.stringify({ | |
'bullet': $("#name").val(), | |
'videoId': '19', | |
'user': '123465' | |
})); | |
} |
然后我修改连接的方法:改成我们指定的通道,因为在同一个项目所以不需要利用 http 或者 ws 去连接 websocket 服务;第二个地址是订阅的地址,之所以需要用 /user/
是因为后端那个指定发送的时候会自动拼接上这个地址,所以我们必须开放这个并且订阅。
function connect() { | |
var socket = new SockJS('/dreamlandWs'); | |
stompClient = Stomp.over(socket); | |
stompClient.connect({}, function (frame) { | |
setConnected(true); | |
console.log('Connected: ' + frame); | |
// stompClient.subscribe('/topic/message', function (greeting) { | |
// showGreeting(greeting.body); | |
// }); | |
stompClient.subscribe('/user/19/bullet', function (greeting) { | |
showGreeting(greeting.body); | |
}); | |
}); | |
} |
# 6、启动项目并且验证
页面启动后访问 localhost:8080 即可
点击 connect,然后输入你要发送的消息,点击 send,会收到自己发送的消息
本篇内容就到此为止了,下一篇来基于此篇的内容实现弹幕效果