基于STOMP协议的WebSocket

 

使用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;
        }
 
    }

对以上代码最好的解析就是官方的图:

基于STOMP协议的WebSocket_第1张图片

 

基于STOMP协议的WebSocket_第2张图片

 

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客户端:

 

 

你可能感兴趣的:(Spring)