WebSocket 为浏览器和服务器提供了双工异步通信的功能,即浏览器可以向服务器发送信息,反之也成立。
WebSocket 是通过一个 socket 来实现双工异步通信能力的,但直接使用 WebSocket ( 或者 SockJS:WebSocket 协议的模拟,增加了当前浏览器不支持使用 WebSocket 的兼容支持) 协议开发程序显得十分繁琐,所以使用它的子协议 STOMP。
STOMP(Simple Text-Orientated Messaging Protocol) 面向消息的简单文本协议
WebSocket是一个消息架构,不强制使用任何特定的消息协议,它依赖于应用层解释消息的含义;
与处在应用层的HTTP不同,WebSocket处在TCP上非常薄的一层,会将字节流转换为文本/二进制消息,因此,对于实际应用来说,WebSocket的通信形式层级过低,因此,可以在 WebSocket 之上使用 STOMP协议,来为浏览器 和 server间的 通信增加适当的消息语义。
STOMP 与 WebSocket 的关系:
STOMP帧由命令,一个或多个头信息、一个空行及负载(文本或字节)所组成;
其中可用的COMMAND 包括:
CONNECT、SEND、SUBSCRIBE、UNSUBSCRIBE、BEGIN、COMMIT、DISCONNECT
org.springframework.boot
spring-boot-starter-websocket
实现 WebSocketMessageBrokerConfigurer 接口,注册一个 STOMP 节点,配置一个广播消息代理
@Configuration
// @EnableWebSocketMessageBroker 注解用于开启使用 STOMP 协议来传输基于代理(MessageBroker)的消息,这时候控制器(controller)
// 开始支持@MessageMapping,就像是使用 @requestMapping 一样。
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//注册一个名为 /getName 的 Stomp 节点(endpoint),并指定使用 SockJS 协议。
registry.addEndpoint("/getName").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 广播式配置名为 /getName/getResponse 消息代理 , 这个消息代理必须和 controller 中的 @SendTo 配置的地址前缀一样或者全匹配
registry.enableSimpleBroker("/getName/getResponse");
}
}
客户端发送给服务器:
public class Client2ServerMessage {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@RestController
public class WebSocketController {
@Autowired
private SimpMessagingTemplate messagingTemplate;
@MessageMapping("/hello") // @MessageMapping 和 @RequestMapping 功能类似,浏览器向服务器发起请求时,映射到该地址。
@SendTo("/getName/getResponse") //如果服务器接受到了消息,就会对订阅了 @SendTo 括号中的地址的浏览器发送消息。
public Server2ClientMessage getName(Client2ServerMessage message){
return new Server2ClientMessage("Hello," + message.getName() + "!");
}
}
Spring Boot+WebSocket
@Controller
public class ViewController {
@GetMapping("/getName")
public String getView(){
return "getName";
}
}
第一步:打开浏览器,访问 http://localhost:8080/getName
第二步:点击链接,输入名字
第三步:点击发送