飞道的博客

spring中使用webSocket

561人阅读  评论(0)

WebSocket介绍

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。

WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

协议有两部分,握手和数据传输。
握手是基于http协议的
来自客户端的握手形式如下:

来自服务器的握手形式如下:

字段说明:

客户端实现

websocket对象
实现 WebSockets 的 Web 通过WebSocket 对象公开所有的必需的客户端功能。
以下 API 用于创建 WebSocket 对象:

var ws = new WebSocket(url);
//参数url格式说明: ws://ip地址端口号/资源名称


websocket方法

引入POM依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>4.2.4.RELEASE</version>
</dependency>

WebSocket入口配置

@Configuration  
@EnableWebSocket  
public class WebSocketConfig implements WebSocketConfigurer {
     
    /** 
     * 注册handle 
     * @see org.springframework.web.socket.config.annotation.WebSocketConfigurer#registerWebSocketHandlers(org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry) 
     */  
    @Override  
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
     
          registry.addHandler(myHandler(), "/testHandler.do").addInterceptors(new WebSocketInterceptor());  
          registry.addHandler(myHandler(), "/socketJs/testHandler.do").addInterceptors(new WebSocketInterceptor()).withSockJS();  
  
    }  
      
    @Bean  
    public WebSocketHandler myHandler(){
     
        return new MyMessageHandler();  
    }  
}
  1. 实现WebSocketConfigurer接口,重写registerWebSocketHandlers方法,这是一个核心实现方法,配置websocket入口,允许访问的域、注册Handler、SockJs支持和拦截器。
  2. registry.addHandler注册和路由的功能,当客户端发起websocket连接,把/path交给对应的handler处理,而不实现具体的业务逻辑,可以理解为收集和任务分发中心。
  3. addInterceptors,是为handler添加拦截器,可以在调用handler前后加入我们自己的逻辑代码。

创建拦截器

public class WebSocketInterceptor extends HttpSessionHandshakeInterceptor {
   
	@Override
	public boolean beforeHandshake(ServerHttpRequest request,
			ServerHttpResponse response, WebSocketHandler wsHandler,
			Map<String, Object> attributes) throws Exception {
   
		if (request instanceof ServletServerHttpRequest) {
   
			ServletServerHttpRequest serverHttpRequest = (ServletServerHttpRequest) request;
			// 获取参数
			String userId = serverHttpRequest.getServletRequest().getParameter(
					"userId");
			attributes.put("currentUser", userId);
		}

		return true;
	}

	// 初次握手访问后
	@Override
	public void afterHandshake(ServerHttpRequest serverHttpRequest,
			ServerHttpResponse serverHttpResponse,
			WebSocketHandler webSocketHandler, Exception e) {
   

	}
}

beforeHandshake,在调用handler前处理方法。常用在登录用户信息,绑定WebSocketSession,在handler里根据用户信息获取WebSocketSession发送消息。

Handler处理类

public class MyMessageHandler implements WebSocketHandler {
   

	/**
	 * userMap:使用线程安全map存储用户连接webscoket信息
	 * 
	 * @since JDK 1.7
	 */
	private final static Map<String, WebSocketSession> userMap = new new ConcurrentHashMap<String, WebSocketSession>();

	/**
	 * 关闭websocket时调用该方法
	 * 
	 * @see org.springframework.web.socket.WebSocketHandler#afterConnectionClosed(org.springframework.web.socket.WebSocketSession,
	 *      org.springframework.web.socket.CloseStatus)
	 */
	@Override
	public void afterConnectionClosed(WebSocketSession session,
			CloseStatus status) throws Exception {
   
		String userId = this.getUserId(session);
		if (StringUtils.isNoneBlank(userId)) {
   
			userMap.remove(userId);
			System.err.println("该" + userId + "用户已成功关闭");
		} else {
   
			System.err.println("关闭时,获取用户id为空");
		}

	}

	/**
	 * 建立websocket连接时调用该方法
	 * 
     *  org.springframework.web.socket.WebSocketHandler#afterConnectionEstablished(org.springframework.web.socket.WebSocketSession)
	 */
	@Override
	public void afterConnectionEstablished(WebSocketSession session)
			throws Exception {
   
		String userId = this.getUserId(session);
		if (StringUtils.isNoneBlank(userId)) {
   
			userMap.put(userId, session);
			session.sendMessage(new TextMessage("建立服务端连接成功!"));
		}

	}

	/**
	 * 客户端调用websocket.send时候,会调用该方法,进行数据通信
	 * 
	 * org.springframework.web.socket.WebSocketHandler#handleMessage(org.springframework.web.socket.WebSocketSession,
	 *      org.springframework.web.socket.WebSocketMessage)
	 */
	@Override
	public void handleMessage(WebSocketSession session,
			WebSocketMessage<?> message) throws Exception {
   

	}

	/**
	 * 传输过程出现异常时,调用该方法
	 * 
	 * org.springframework.web.socket.WebSocketHandler#handleTransportError(org.springframework.web.socket.WebSocketSession,
	 *      java.lang.Throwable)
	 */
	@Override
	public void handleTransportError(WebSocketSession session, Throwable e)
			throws Exception {
   
		WebSocketMessage<String> message = new TextMessage("异常信息:"
				+ e.getMessage());
		session.sendMessage(message);
	}

	/**
	 * 
	 *   org.springframework.web.socket.WebSocketHandler#supportsPartialMessages()
	 */
	@Override
	public boolean supportsPartialMessages() {
   

		return false;
	}

	/**
	 * sendMessageToUser:发给指定用户
	 * 
	 */
	public void sendMessageToUser(String userId, String contents) {
   
		WebSocketSession session = userMap.get(userId);
		if (session != null && session.isOpen()) {
   
			try {
   
				TextMessage message = new TextMessage(contents);
				session.sendMessage(message);
			} catch (IOException e) {
   
				e.printStackTrace();
			}
		}
	}

	/**
	 * sendMessageToAllUsers:发给所有的用户
	 * 
	 */
	public void sendMessageToAllUsers(String contents) {
   
		Set<String> userIds = userMap.keySet();
		for (String userId : userIds) {
   
			this.sendMessageToUser(userId, contents);
		}
	}

	/**
	 * getUserId:获取用户id
	 * 
	 * @author liuchao
	 * @param session
	 * @return
	 * @since JDK 1.7
	 */
	private String getUserId(WebSocketSession session) {
   
		try {
   
			String userId = (String) session.getAttributes().get("currentUser");
			return userId;
		} catch (Exception e) {
   
			e.printStackTrace();
		}
		return null;
	}

客户端连接

<script type="text/javascript">
    $(function(){
   
        	var host= window.location.host;
            var websocket;
            if ('WebSocket' in window) {
   
                websocket = new WebSocket("ws://"+host+"/testHandler.do?userId=9528");
            } else if ('MozWebSocket' in window) {
   
                websocket = new MozWebSocket("ws://"+host+"/testHandler.do?userId=9528");
            } else {
   
                websocket = new SockJS("http://"+host+"/socketJs/testHandler.do?userId=9528");
            }
            websocket.onopen = function (evnt) {
   
                console.log("链接服务器成功!")
            };
            websocket.onmessage = function (evnt) {
   
                console.log(evnt.data);
                $("#message").html(evnt.data);
            };
            websocket.onerror = function (evnt) {
   
            	console.log("websocket错误");
            };
            websocket.onclose = function (evnt) {
   
                console.log("与服务器断开了链接!")
            }
            $('#send').bind('click', function() {
   
                send();
            });
            function send(){
   
                if (websocket != null) {
   
                    var message = document.getElementById('message').value;
                    websocket.send(message);
                } else {
   
                    alert('未与服务器链接.');
                }
            }
    });
</script>

转载:https://blog.csdn.net/fffvdgjvbsfkb123456/article/details/116465394
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场