Spring websocket over STOMP使用指南

启用STOMP

Spring框架提供基于websocket的STOMP支持,需要使用spring-messagingspring-websocket模块。
下面的配置中,注册了一个前缀为/portfolio的stomp终端,客户端可以使用该url来建立websocket连接。
Message的destination如果是以/app开头,则会转发给响应的消息处理方法(如使用@MessageMapping注解的方法),如果是以/topic,/queue开头则会被转发给消息代理(broker),由broker广播给连接的客户端。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/portfolio").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.setApplicationDestinationPrefixes("/app");//这个前缀不需要与web项目名相同,可以自己随意指定
        config.enableSimpleBroker("/topic", "/queue");//这里配置了两个前缀,若是destination以这两个前缀开头,则会转发给该Broker
    }

}

或者使用XML

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:websocket="http://www.springframework.org/schema/websocket"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/websocket
        http://www.springframework.org/schema/websocket/spring-websocket.xsd">

    <websocket:message-broker application-destination-prefix="/app">
        <websocket:stomp-endpoint path="/portfolio">
            <websocket:sockjs/>
        websocket:stomp-endpoint>
        <websocket:simple-broker prefix="/topic, /queue"/>
    websocket:message-broker>

beans>

这里使用js作为stomp的客户端,需要使用stomp.js和sockjs-client,/spring-websocket-portfolio是web app的项目名,/portfolio是stomp终端名

var socket = new SockJS("/spring-websocket-portfolio/portfolio");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
}

若不适用sockjs,则可以使用原生的websocket api

var socket = new WebSocket("/spring-websocket-portfolio/portfolio");
var stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {
}

消息流

Spring websocket over STOMP使用指南_第1张图片
Message在应用中的流动是这样一个流程,如上图。若destination是以/app开始则会通过request channel交给注解方法来处理,处理完毕根据默认的路径转发给SimpleBroker处理(若不使用默认路径可以用@SendTo来指定路径),处理完毕后交由response channel返回连接的客户端。
若destination是以/topic开头则直接交给SimpleBroker处理。

@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/portfolio");
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/app");
        registry.enableSimpleBroker("/topic");
    }

}

@Controller
public class GreetingController {

    @MessageMapping("/greeting") 
    @SendTo("/topic/greetings")
    public String handle(String greeting) {
        return "[" + getTimestamp() + ": " + greeting;
    }
    @SubscribeMapping("/init")
    public String init(){
         return "init";
    }

}

使用@SubscribeMapping注解,处理client的subscribe请求,被注解的方法将直接返回一个信息给连接的client,不会经过Broker.常用于进行初始化操作。若是在该方法上使用了@SendTo,则会转发至broker处理。

使用Template发送数据

上面我们介绍了如何在controller中发送数据给clients,spring还提供了一个叫做SimpMessagingTemplate的模板,以便我们在应用的任何地方发送数据给Broker

@Controller
public class GreetingController {
    @Autowired
    private SimpMessagingTemplate template;

    @RequestMapping(path="/greetings", method=POST)
    public void greet(String greeting) {
        String text = "[" + getTimestamp() + "]:" + greeting;
       template.convertAndSend("/topic/greetings", text);
    }

}

@Service
public class GreetingServiceImpl {
    @Autowired
    private SimpMessagingTemplate template;

    public void greet(String greeting) {
        String text = "[" + getTimestamp() + "]:" + greeting;
        template.convertAndSend("/topic/greetings", text);
    }

}

常用的注解

destination映射是支持Ant风格的,如"/foo*", "/foo/**"。也支持路径参数"/foo/{id}",可以在方法参数中使用@DestinationVariable注解来引用它
@MessageMapping 注解的方法可以使用下列参数:
* 使用@Payload方法参数用于获取消息中的payload(即消息的内容)
* 使用@Header 方法参数用于获取特定的头部
* 使用@Headers方法参数用于获取所有的头部存放到一个map中
* java.security.Principal 方法参数用于获取在websocket握手阶段使用的用户信息

你可能感兴趣的:(websocket)