有时候前端需要实时的获取后端的信息,比如订单的消息,发货之类的通知,实时的服务器信息,股票信息等。有一种方法是ajax轮训,就是间隔一段时间查询服务器一次,但是这种方式对服务器不太友好。所以,还有另一种方法,websocket。
pom文件引入依赖
org.springframework.boot
spring-boot-starter-websocket
写一个配置类,继承AbstractWebSocketMessageBrokerConfigurer,这个类配置的是关于STOMP协议。前端使用的是stomp.js,关于stomp.js可以看一下这一篇博客:https://www.cnblogs.com/goloving/p/10746378.html 。stomp.js 具体的使用方法下面会写。
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketStompConfig extends AbstractWebSocketMessageBrokerConfigurer {
/**
* 注册stomp的端点,发布或者订阅消息时需要连接此端点
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/endpoint").setAllowedOrigins("*").withSockJS();
}
/**
* 配置信息代理(中介转发)
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 订阅Broker名称
registry.enableSimpleBroker("/queue","/topic","/chat");
// 全局使用的消息前缀(客户端订阅路径上会体现出来)
registry.setApplicationDestinationPrefixes("/app");
}
}
首先定义两个传输数据的对象
public class InMessage {
private String from;
private String to;
private LocalDateTime time = LocalDateTime.now();
private String content;
//省略setter和getter
}
public class OutMessage {
private String from;
private LocalDateTime time = LocalDateTime.now();
private String content;
//省略setter和getter
}
使用起来也是很简单,有两种方法。
value属性值的第一值 /topic 必须在enableSimpleBroker中配置,@MessageMapping和@RequestMapping的作用类似。
@Controller
public class GameInfoController {
@MessageMapping("/v1/game_chat")
@SendTo("/topic/game_chat")
public OutMessage gameInfo(InMessage message){
return new OutMessage("",message.getContent());
}
}
destination的第一个值必须在上面 的enableSimpleBroker中配置,与@SendTo的value使用方法一致。
@Component
public class WebSocketService {
@Autowired
private SimpMessagingTemplate template;
public void sengTextMsg(String destination,Object message){
template.convertAndSend(destination,message);
}
}
@Controller
public class GameInfoV2Controller {
@Autowired
private WebSocketService webSocketService;
@MessageMapping("/v2/chat")
public void gameInfo(InMessage message){
webSocketService.sendTopicMessage("/topic/game_rank", message);
}
}
这两种方法的主要区别在于@SendTo的路径是写死的,SimpMessagingTemplate的路径可以动态设置。
以上都是群发消息,我们可以在路径上绑定id信息,这样就可以给特定的人推送消息了。在WebSocketService 中添加以下方法。
public void sendChatMessage(InMessage message) {
template.convertAndSend("/chat/single/"+message.getTo(),new OutMessage(message.getFrom(),message.getContent()));
}
@Controller
public class ChatRoomV3Controller {
@Autowired
private WebSocketService webSocketService;
@MessageMapping("v3/single/chat")
public void singleChat(InMessage message){
webSocketService.sendChatMessage(message);
}
}
我们可以使用@Scheduled注解来实现实时的数据推送,先在启用类上添加@EnableScheduling注解
再添加一个方法
public void sendServerInfo() {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
template.convertAndSend("/topic/server_info",new OutMessage(now.format(df)));
}
然后直接使用@Scheduled注解一个方法就可以了,每秒推送一次数据
@Controller
public class ServerInfoV4Controller {
@Autowired
private WebSocketService webSocketService;
@Scheduled(fixedRate = 1000)
public void sendServerInfo(){
webSocketService.sendServerInfo();
}
}
使用起来也是挺简单的。看注释应该就明白了。要注意的是 subscribe的地址在后台要有,也就是和@SendTo、destination的值对应。
Insert title here
还有基于H5的websocket,后面会再写