Spring4.3.3 WebSocket-STOMP协议集成 (2)-WebSocket-stomp子协议通讯小栗子

        前面说到,使用websocket通讯,现在说说应用上的通讯,stomp - streaming / simple text oriented protocol. 流/简单 文本协议。应用方面,一般采用该种协议,是websocket协议的一个子协议,了解一下既可。
        stomp协议,配置时注意一个地方,stomp协议使用的中继器(路由)或者叫消息中介,默认在configureMessageBroker方法中,registry.enableSimpleBroker是使用内存中介,不依赖第三方组件,registry.enableStompBrokerRelay是使用第三方中间件,需要事先下载安装中间件,如activeMQ/RabbitMQ.本例子中使用内存中继。

        具体代码实现:

        1. WebSocketMessageBrokerConfigurer配置类,继承AbstractWebSocketMessageBrokerConfigurer重写下面方法。

package com.websocket.stomp;

import java.util.List;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
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.config.annotation.WebSocketTransportRegistration;

/**
 * stomp websocket的子协议,stomp: simple/streaming text oriented message protocol. 简单/流 文本消息协议, 
 * 选择使用内存中级,还是使用activeMQ等中间件服务器
 * @author tomZ
 * @date 2016年11月3日
 * @desc TODO
 */
@Configuration
@EnableWebSocketMessageBroker
public class MyWebSocketMessageBrokerConfig extends AbstractWebSocketMessageBrokerConfigurer {

	/**
	 * 连接的端点,客户端建立连接时需要连接这里配置的端点
	 */
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		//为java stomp client提供链接
		registry.addEndpoint("/client")
		.setAllowedOrigins("*")
		.setHandshakeHandler(new MyHandshakeHandler())
		.addInterceptors(new MyHandshakeInterceptor());
		
		//为js客户端提供链接
		registry.addEndpoint("/hello")
		.setAllowedOrigins("*")
		.setHandshakeHandler(new MyHandshakeHandler())
		.addInterceptors(new MyHandshakeInterceptor())
		.withSockJS();
	}
	/**
	 * applicationDestinationPrefixes应用前缀,所有请求的消息将会路由到@MessageMapping的controller上,
	 * enableStompBrokerRelay是代理前缀,而返回的消息将会路由到代理上,所有订阅该代理的将收到响应的消息。
	 * 
	 */
	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		registry.setApplicationDestinationPrefixes("/app");
		registry.setUserDestinationPrefix("/user");
		registry.enableSimpleBroker("/topic", "/queue")
//		registry.enableStompBrokerRelay("/topic", "/queue")
		//下面这配置为默认配置,如有变动修改配置启用就可以了
//		.setRelayHost("127.0.0.1") //activeMq服务器地址
//		.setRelayPort(61613)//activemq 服务器服务端口
//		.setClientLogin("guest")	//登陆账户
//		.setClientPasscode("guest") // 
		;
	}
	
	/**
	 * 消息传输参数配置
	 */
	@Override
	public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
//		super.configureWebSocketTransport(registration);
		registration.setMessageSizeLimit(8192).setSendBufferSizeLimit(8192).setSendTimeLimit(10000);
	}
	
	/**
	 * 输入通道参数设置
	 */
	@Override
	public void configureClientInboundChannel(ChannelRegistration registration) {
//		super.configureClientInboundChannel(registration);
		//线程信息
		registration.taskExecutor().corePoolSize(4).maxPoolSize(8).keepAliveSeconds(60);
	}
	/**
	 * 输出通道参数配置
	 */
	@Override
	public void configureClientOutboundChannel(ChannelRegistration registration) {
//		super.configureClientOutboundChannel(registration);
		//线程信息
		registration.taskExecutor().corePoolSize(4).maxPoolSize(8);
	}
	
	@Override
	public boolean configureMessageConverters(List messageConverters) {
//		return super.configureMessageConverters(messageConverters);
		return true;
	}

}

        Handler类:处理器类

package com.websocket.stomp;

import java.security.Principal;
import java.util.Map;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

/**
 * stomp 处理器
 * @author tomZ
 * @date 2016年11月4日
 * @desc TODO
 */
public class MyHandshakeHandler extends DefaultHandshakeHandler {

	///该方法可以重写用来为用户 添加标识 返回principal
	@Override
	protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler,
			Map attributes) {
		// TODO Auto-generated method stub
		return super.determineUser(request, wsHandler, attributes);
	}
	
}
        Interceptor类。拦截器

package com.websocket.stomp;

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

/**
 * stomp握手拦截器
 * @author tomZ
 * @date 2016年11月4日
 * @desc TODO
 */
public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor {
	private static final Logger logger = LoggerFactory.getLogger( MyHandshakeInterceptor.class);
	
	@Override
	public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
			Map attributes) throws Exception {
		logger.info("===============before handshake=============");
		return super.beforeHandshake(request, response, wsHandler, attributes);
	}
	
	@Override
	public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
			Exception ex) {
		logger.info("===============after handshake=============");
		super.afterHandshake(request, response, wsHandler, ex);
	}
}

         2. 最后在spring-context.xml (application-context.xml)中扫描上面类所在的包即可。

         3. controller, @MessageMapping用法和@RequestMapping相似,@SendTo是将消息发到指定的映射路由uri上去,@Subscribe是订阅uri注解,此外还有@SendToUser/@DestinationVariable等注解,可以查一下。

     

package com.tom.jeesite.web.stomp;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 
 * @author tom
 * @version 2016-06-12
 */
@Controller
public class MyStompTestController {
	/**
	 * @MessageMapping 是app路由地址,客户端请求将交由其处理,@SendTo是返回消息路由到指定地址,订阅该地址的将接收到消息
	 * @param incoming
	 * @return
	 */
	@MessageMapping("/hi")
	@SendTo("/topic/hi")
	public String handleHi(String incoming) {
		System.out.println("receive message : " + incoming);
		return "hello, " + incoming; 
	}
	/**
	 * 订阅,当有客户端订阅该内容,会有一次性响应
	 * @return
	 */
	@SubscribeMapping("/subscribeme")
	public String subscribeThing() {
		System.out.println("subscribe message called.");
		return "thank you subscribe my channel";
	}
	
}


         4. Jsp页面:

     

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


<%
	String path = request.getContextPath();
	String basePath = request.getServerName() + ":" + request.getServerPort() + path + "/";
	
%>



    <%--  --%>
    
    
    
    
    
    
    
    
    
    
    <%--  --%>
    
    
    stomp测试





       启动运行,效果如下:

       浏览器:

Spring4.3.3 WebSocket-STOMP协议集成 (2)-WebSocket-stomp子协议通讯小栗子_第1张图片

       服务器:

Spring4.3.3 WebSocket-STOMP协议集成 (2)-WebSocket-stomp子协议通讯小栗子_第2张图片

如果出现spring扫描不到@MessageMapping注解方法的情况,在AbstractWebSocketMessageBrokerConfigurer的实现方法上加上注解:@ComponentScan("controller所在的包名")

你可能感兴趣的:(Spring)