使用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 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
org.springframework
spring-websocket
${spring.version}
org.springframework
spring-messaging
${spring.version}
建议使用第二种,好处:
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客户端: