概述
使用spring websocket 有两种方式:
1.SpringFramework提供了一个WebSocketAPI,您可以使用它来编写处理WebSocket消息的客户端和服务器端应用程序。
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(myHandler(), "/myHandler");
}
@Bean
public WebSocketHandler myHandler() {
return new MyHandler();
}
}
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.TextMessage;
public class MyHandler extends TextWebSocketHandler {
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) {
// ...
}
}
2.Enable STOMP
import java.security.Principal;
import java.util.Map;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
/**
* @author lyy
*/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/stomp-endpoint").setHandshakeHandler(new DefaultHandshakeHandler() {
@Override
protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
String name= ((ServletServerHttpRequest) request).getServletRequest().getParameter("username");
return new MyPrincipal(name);
}
})
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
//当客户端发送消息或订阅消息时,url路径开头如果是/app/xxx 时,会先解析stomp协议,然后路由到@controller的@MessageMapping("/xxx")的方法上执行。
//如果不设置,客户端所有发送消息或订阅消息时、都将去匹配@messageMapping。所以最好还是配置上。
config.setApplicationDestinationPrefixes("/app");
//声明消息中间件Broker的主题名称,当向这个主题下发送消息时(js: stompclient.send("/topic/target1",{},"hello" ) ),订阅当前主题的客户端都可以收到消息。
//注意:js 客户端如果发送时、直接是/topic/xxx,spring收到消息会直接发送给broker中。
// 点对点发送时:enableSimpleBroker 中要配置 /user才可能用: template.convertAndSendToUser("zhangsan","/aaa/hello","111"),否则收不到消息。
config.enableSimpleBroker("/topic","/user");
//点对点发送前缀
config.setUserDestinationPrefix("/user");
}
class MyPrincipal implements Principal{
private String key;
public MyPrincipal(String key) {
this.key = key;
}
@Override
public String getName() {
return key;
}
}
对以上代码最好的解析就是官方的图:
java推送消息方式 :
/**
* @author lyy
*/
@Controller
@EnableScheduling
public class PayTestController {
@Autowired
public SimpMessagingTemplate template;
//这个注解其实就是用来定义接受客户端发送消息的url(不能是topic开头,如果是topic直接发送给broker了,要用/app/hello)
//如果有返回只则会将返回的内容转换成stomp协议格式发送给broker(主题名:/topic/hello)。如果要换主题名可使用@sentTo
//@SubscribeMapping注解和@messageMapping差不多,但不会再把内容发给broker,而是直接将内容响应给客户端,
@MessageMapping("/hello")
public void greeting(String content) throws Exception {
System.out.println("收到内容: "+content );
}
//广播推送消息
@Scheduled(fixedRate = 10000)
public void sendTopicMessage() {
System.out.println("后台广播推送!");
this.template.convertAndSend("/topic/hello","test");
}
//点对点
@Scheduled(fixedRate = 10000)
public void sendQueueMessage() {
System.out.println("后台一对一推送!");
this.template.convertAndSendToUser("zhangsan","/aaa/hello","111");
}
}
一共就两种,注解或SimpMessagingTemplate 。
注意:js是可以直接填写主题路径来发送消息给订阅者的。所以最好有认证限制。省得客户端乱推送消息
后台推送流程:template.convertAndSend("xxx")将消息转换成stomp格式、然后发送到broker中,broker利用websocket链接发送消息给所以的订阅者。
js推送流程: stompClient.send("/topic/hello",{},"222") 利用websocket链接、将stomp格式的消息发送给Spring 的clientInboundChannel,Spring转发到broker中(brokerChannel),broker利用websocket链接发送消息给所以的订阅者。
pom
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
建议使用第二种,好处:
1.更加简单,灵活。
2.不用自己管理websocket session
3.可以很方便的集成 消息代理(如RabbitMQ、ActiveMQ和其他)来管理订阅和广播消息。提高效率
4.利用stomp消息协议、规范传输的消息格式。客户端和服务器端的交互,只是利用websocket 的链接。
5.可以利用推送消息来保持sesssion。要集成spring session(原理就是推送消息时刷新session的最后更新时间)
https://docs.spring.io/spring-session/docs/current/reference/html5/guides/boot-websocket.html
6,支持topic订阅模式,和点对点发送消息。
js客户端:
<script type="text/javascript">
//建立连接对象(还未发起连接)
var socket=new SockJS("/platform/stomp-endpoint?username=aaaa");
// 获取 STOMP 子协议的客户端对象
var stompClient = Stomp.over(socket);
// 向服务器发起websocket连接并发送CONNECT帧
stompClient.connect( {},
function connectCallback (frame) {
// 连接成功时(服务器响应 CONNECTED 帧)的回调方法
console.log('已连接【' + frame + '】');
//订阅一个消息
stompClient.subscribe('/user/zhangsan/aaa/hello',
function (response) {
console.log("zhangsan: "+response.body);
});
},
function errorCallBack (error) {
// 连接失败时(服务器响应 ERROR 帧)的回调方法
console.log('连接失败【' + error + '】');
});
//发送消息
function send(){
//可以理解成直接让应用将推送消息转发到broker中。
//stompClient.send("/user/zhangsan/aaa/hello",{},"222")
//先进@messageMapping的controller方法,再决定消息的去向
stompClient.send("/app/hello",{},"222")
}
//这里10妙后才调用发送,如果立马调用发送一般会失败。因为链接状态还没完成。
setTimeout(send,10000)
</script>
最后
以上就是平淡鸭子为你收集整理的基于STOMP协议的WebSocket的全部内容,希望文章能够帮你解决基于STOMP协议的WebSocket所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复