使用spring4实现websocket连接(二)


本文摘自classinstance.cn。

上一篇关于使用spring4实现websocket连接的问题,我只是分享了大致如何实现,要想应用到实际项目中,还要考虑2个问题:

1.是否区分用户,用户连上websocket时,每次发消息给用户时,是否要区分用户,是不是每个人收到的消息不一样,这里就涉及获取httpSession的问题了。

2.我们项目中一般不会只有一个websocket收发消息,有时一个是处理用户消息,一个是处理其他的,举个例子:批处理时的进度实时反馈等,都会用到websocket

所以针对上面这两个问题,我决定再深入研究了下,pom文件还是参考上一篇文章里的,并没有新加入jar包,下面直接上代码吧,类也是上一篇里的那两个类,只是新加入了一些完善的代码,代码里都有提到上面这两个问题:

HandshakeInterceptor.java

package com.solr.websocket;

import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor{

	//websocket握手时处理httpsession,取用户标识,如果你的应用不区分用户,当然这里就可以不用取sesion了
	@Override  
    public boolean beforeHandshake(ServerHttpRequest request,  
            ServerHttpResponse response, WebSocketHandler wsHandler,  
            Map<String, Object> attributes) throws Exception {  
        System.out.println("Before Handshake");  
        //演示怎么把httpsession放入websocketsession里,区分用户
        HttpSession session = getSession(request);
        if (session != null) {
        	String userId = session.getId();
            attributes.put("userId", userId);
        }
        return super.beforeHandshake(request, response, wsHandler, attributes);  
    }  
  
    @Override  
    public void afterHandshake(ServerHttpRequest request,  
            ServerHttpResponse response, WebSocketHandler wsHandler,  
            Exception ex) {  
    }
    //取httpSession
    private HttpSession getSession(ServerHttpRequest request) {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest serverRequest = (ServletServerHttpRequest) request;
            return serverRequest.getServletRequest().getSession();
        }
        return null;
    }
}

WebsocketHandler.java

package com.solr.websocket;

import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class WebsocketHandler extends TextWebSocketHandler {

	private final static Map<String, WebSocketSession> users = new ConcurrentHashMap<String, WebSocketSession>();

	public static Map<String, WebSocketSession> getUsers() {
		return users;
	}
	static{
		SendMessageThread sendThread = new SendMessageThread();
		Thread t = new Thread(sendThread);
		t.start();
	}

	/**
	 * 连接成功时候,会触发页面上的onopen方法
	 */
	public void afterConnectionEstablished(WebSocketSession session)
			throws Exception {

		Map<String, Object> attributes = session.getHandshakeAttributes();
		if (attributes != null && attributes.size() > 0) {
			String userId = attributes.get("userId").toString();//只是为了演示这里可以取httpsession的id,如果你的应用要区分用户,就可以在此处取httpsession
			System.out.println("userId:" + userId);
			String websocketId = session.getId();//websocket id
			users.put(websocketId, session);
		}
		System.out.println("connect to the websocket success......当前数量:"+ users.size());
	}

	/**
	 * 关闭连接时触发(关闭掉页面也会触发)
	 */
	public void afterConnectionClosed(WebSocketSession session,
			CloseStatus closeStatus) throws Exception {
		System.out.println("websocket connection closed......");
		String websocketId = session.getId();//websocket id
		users.remove(websocketId);
		System.out.println("剩余在线用户" + users.size());
	}

	/**
	 * 异常处理
	 */
	public void handleTransportError(WebSocketSession session,
			Throwable exception) throws Exception {
		if (session.isOpen()) {
			session.close();
		}
		System.out.println("websocket connection closed......");
		String websocketId = session.getId();//websocket id
		users.remove(websocketId);
	}

	// 收消息
	@Override
	protected void handleTextMessage(WebSocketSession session,
			TextMessage message) throws Exception {
		super.handleTextMessage(session, message);
		System.out.println("收到消息:" + message.getPayload());
		
	}

	static class SendMessageThread implements Runnable {
		public void run() {
			while (true) {
				try {
					Map<String, WebSocketSession> map = WebsocketHandler.getUsers();
					Set<String> keySet = map.keySet();
					for (String key : keySet) {
						WebSocketSession webSocketSession = map.get(key);

						if (webSocketSession.isOpen()) {
							String message = "现在时间:"+ new Date().toLocaleString();
							TextMessage textMessage = new TextMessage(message);
							webSocketSession.sendMessage(textMessage);
						}
					}
					//定时5秒发一次消息
					Thread.sleep(5000l);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}

这样就是比较接近实际项目里的应用了,触发发送消息我上面的代码是定时5秒发一次消息,你也可以根据你的项目把调用发送消息的代码写在service或者springmvc的controller里,关键是看你的具体业务。

阅读剩余部分

相关阅读 >>

spring如何获取配置在application.properties文件中属性的值?

使用spring4实现websocket连接(二)

使用spring4实现websocket连接

spring、springmvc、springboot和springcloud的区别

spring事务管理与查询是否需要事务以及可重复读的问题

更多相关阅读请进入《spring4》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...