websocket带参数实时推送消息,前后端的实现

SSM+JSP项目中加入了websocket的消息推送
app端与网页端通信
以下代码只是讲解答大体思路

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ include file="/WEB-INF/views/include/taglib.jsp"%>
<html>
<head>
//外链各种样式
<!-- <link rel="stylesheet"
	href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet"
	href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
<script src="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> -->
<meta name="decorator" content="v5" />
<link href="${ctxStatic}/v5/css/content.css" type="text/css"
	rel="stylesheet" />
<title></title>
<script type="text/javascript">
//分页
	function page(n, s) {
		$("#pageNo").val(n);
		$("#pageSize").val(s);
		$("#searchForm").submit();
		return false;
	}

	var websocket;
	if ('WebSocket' in window) {
		console.log("此浏览器支持websocket");
		websocket = new WebSocket("ws://192.168.1.172:8080/项目名/webSocketServer?username=${userId}&ie=1");//传参数的方式
	} else if ('MozWebSocket' in window) {
		alert("此浏览器只支持MozWebSocket");
	} else {
		alert("此浏览器只支持SockJS");
	}
	websocket.onopen = function(evnt) {
		$("#tou").html("链接服务器成功!")
	};
	
	//实时显示推送的消息
	websocket.onmessage = function(evnt) {
		if(evnt.data.indexOf("|") >= 0 ){
			var msg=evnt.data.split("|");
			if(msg[1]==1){
				$("#"+msg[0]).html("开");
				$("#"+msg[0]+"2").html("关闭");
			}else{
				$("#"+msg[0]).html("关");
				$("#"+msg[0]+"2").html("开启");
			}
		}else{
			alert(evnt.data);
		}
	};
	
	websocket.onerror = function(evnt) {
		$("#tou").html("遇到了错误")
	};
	
	websocket.onclose = function(evnt) {
		$("#tou").html("与服务器断开了链接!")
	}
	
	$('#send').bind('click', function() {
			senda(111);
	});

	function senda(deviceId,deviceS100Id) {
		var open;
		if($("#"+deviceId).html()=="开"){
			open=0;
		}else{
			open=1;
		}
		var message = deviceId+"|"+open+"|"+deviceS100Id+"|1";
		if (websocket != null) {
			//var message = $("#message").val();
			websocket.send(message);
		} else {
			alert('未与服务器链接.');
		}
	}
</script>
</head>
<body>
	<div class="page-header" id="tou"></div>
	
	<div class="table_wrapper animated fadeInRight">
		<sys:message content="${message}" />
		<table id="contentTable"
			class="table table-striped  table-condensed table-ys "
			style='table-layout: fixed' width="100%">
			<thead>
				<tr>
					<th>门禁编号</th>
					<th>状态</th>
					<th>操作</th>
				</tr>
			</thead>
			<tbody>
				<c:forEach items="${page.list}" var="appDevice">
					<tr>
						<td>${appDevice.deviceId}</td>
						<td id="${appDevice.deviceId}"></td>
						<td><a href="#" onclick="senda('${XXX}','${XXX}')"  id="${XXX}2">开启</a>
						//id为动态生成,方便jq查找
						</td>
					</tr>
				</c:forEach>
			</tbody>
		</table>
		<div class="pagination">${page}</div>
	</div>
</body>
</html>

展示
websocket带参数实时推送消息,前后端的实现


**

## WebSocketConfig.java

**
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements
		WebSocketConfigurer {
	@Override
	public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
		registry.addHandler(WebSocketPushHandler(), "/webSocketServer")
				.addInterceptors(new MyWebSocketInterceptor());
		registry.addHandler(WebSocketPushHandler(), "/sockjs/webSocketServer")
				.addInterceptors(new MyWebSocketInterceptor()).withSockJS();
	}

	@Bean
	public WebSocketHandler WebSocketPushHandler() {
		return new WebSocketPushHandler();
	}
}

**

## MyWebSocketInterceptor.java

**
import org.springframework.core.Constants;
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.HandshakeInterceptor;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import java.util.Map;

/**
 * 此类用来获取登录用户信息并交由websocket管理
 * @author ts
 *
 */
public class MyWebSocketInterceptor extends  HttpSessionHandshakeInterceptor  {

	@Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Before Handshake");
       
       //接受jsp传来的参数
        String userName = ((ServletServerHttpRequest) request).getServletRequest().getParameter("username");
        String ie =  ((ServletServerHttpRequest) request).getServletRequest().getParameter("ie");
        
        //将参数放到attributes
        if(userName!=null){
        	attributes.put("WEBSOCKET_DEVICEID",userName);
        }
        attributes.put("ie",ie);
      
        return super.beforeHandshake(request, response, wsHandler, attributes);
        
    }
    
    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception ex) {
        // TODO Auto-generated method stub
        super.afterHandshake(request, response, wsHandler, ex);
    }
}
**

## WebSocketPushHandler

**
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 消息处理类
 * 
 * @author ts
 * 
 */
public class WebSocketPushHandler implements WebSocketHandler {

	@Autowired
	private DoorStatusService doorStatusService;
	@Autowired
	private AppDeviceService appDeviceService;
	@Autowired
	private SystemService systemService;

	// 保存ie链接
	private static Map<String, WebSocketSession> map = new HashMap<String, WebSocketSession>();

	// 保存app的连接
	private static Map<String, WebSocketSession> mapApp = new HashMap<String, WebSocketSession>();

	// 静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
	private static int onlineCount = 0;

	// 用户进入系统监听
	@Override
	public void afterConnectionEstablished(WebSocketSession session)
			throws Exception {
			//得到参数
		String id = (String) session.getAttributes().get("WEBSOCKET_DEVICEID");
		String ie = (String) session.getAttributes().get("ie");
//1为网页端的连接。0为app端的连接
		if ("1".equals(ie)) {
			map.put(id, session);
			System.out.println("ie成功进入了系统。标识id:" + id);
		} else {
			mapApp.put(id, session);
			System.out.println("app成功进入了系统。标识id:" + id);
		}
		onlineCount++;
		System.out.println("当前在线数:" + onlineCount);

	}

	//发来的消息
	@Override
	public void handleMessage(WebSocketSession session,
			WebSocketMessage<?> message) throws Exception {
			System.out.println("客户端发来的消息:"+message.getPayload());
	}

	// 后台错误信息处理方法
	@Override
	public void handleTransportError(WebSocketSession session,
			Throwable exception) throws Exception {

	}

	// 用户退出后的处理,不如退出之后,要将用户信息从websocket的session中remove掉,这样用户就处于离线状态了,也不会占用系统资源
	@Override
	public void afterConnectionClosed(WebSocketSession session,
			CloseStatus closeStatus) throws Exception {
		if (session.isOpen()) {
			session.close();
		}
		onlineCount--;
		System.out.println("当前在线数:" + onlineCount);

		Collection<WebSocketSession> col = map.values();
		while (true == col.contains(session)) {
			System.out.println("安全退出了系统。。标识id" + map.keySet());
			col.remove(session);
		}
	}

	@Override
	public boolean supportsPartialMessages() {
		return false;
	}

	/**
	 * 给所有的用户发送消息
	 */
	public void sendMessagesToUsers(TextMessage message) {
	}

	/**
	 * 发送消息给ie
	 *  */
	public void sendMessageToUser(String deviceId, TextMessage message,
			User user) {

//编辑消息后sendMessage()方法进行消息推送
		TextMessage message1 = new TextMessage(msg);
	(message1);
				map.get(XXX).sendMessage(message1);
		
	}
	
	//推送到app
	public void sendMessageToapp(String deviceId, TextMessage message,User user,String deviceS100Id){
		// 遍历map。找到对应的app
		for (String key : mapApp.keySet()) {
			if (key.equals(deviceId)) {
				try {
					if (mapApp.get(key).isOpen()) {
						mapApp.get(key).sendMessage(message);
						System.out.println("发送成功,设备码:" + key);
						// 保存数据库
						XXXX
						return;
					} else {
						System.out.println("设备不在线,未发送,设备号:" + deviceId);
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		System.out.println("提示:设备未上线!" + deviceId);
		TextMessage message1 = new TextMessage("提示:设备未上线!");
		try {
			map.get(user.getId()).sendMessage(message1);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
}