springboot集成websocket

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_16855077/article/details/82858214

1.pom.xml

<!-- webSocket -->  
 <dependency>     
       <groupId>org.springframework.boot</groupId>      
        <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2.后台代码

package com.cloudtech.web.controller;
 
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.cloudtech.web.dubbo.BaseDataResult;
import com.cloudtech.web.entity.WarnNoticeInfo;
import com.cloudtech.web.util.Constans;
import com.cloudtech.web.util.JacksonUtil;
//@ServerEndpoint("/websocket/{user}")
@Component
@ServerEndpoint(value = "/websocket/{id}/{operatorId}")
public class WebSocketServer{
	
	private static final Logger log = LoggerFactory.getLogger(WarnController.class);
	
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    static public final ConcurrentMap<Integer, ConcurrentMap<String,WebSocketServer>> webSocketSet = new ConcurrentHashMap<>();
    //用户集合  key:账号id   value:账号明细
    static public final ConcurrentMap<Integer, Integer> principalMaps = new ConcurrentHashMap<>();
    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    
  
    /**
     * 连接建立成功调用的方法
     * @param id    账号id
     * @param operatorId  运营商id
     * @param session
     */
    @OnOpen
    public void onOpen(@PathParam("id") Integer id,@PathParam("operatorId") Integer operatorId,Session session) {
        this.session = session;
        
        ConcurrentMap<String, WebSocketServer> concurrentMap = webSocketSet.get(id);
        if(concurrentMap == null){
        	concurrentMap = new ConcurrentHashMap<>(); 
        }
        concurrentMap.put(session.getId(),this);
        webSocketSet.put(id, concurrentMap);
        
        //遗留问题:如果没有预警权限可能也会创建连接,这里暂不考虑
        //按道理应该可以从session中取到对应的值,卡了半天,通过前端传值
        principalMaps.put(id, operatorId);
        
        addOnlineCount();           //在线数加1
        log.info("有新连接加入!当前在线人数为" + getOnlineCount());
        
        
    }
	//	//连接打开时执行
	//	@OnOpen
	//	public void onOpen(@PathParam("user") String user, Session session) {
	//		currentUser = user;
	//		System.out.println("Connected ... " + session.getId());
	//	}
 
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam("id") Integer id,Session session) {
    	ConcurrentMap<String, WebSocketServer> concurrentMap = webSocketSet.get(id);
    	if(concurrentMap != null){
    		concurrentMap.remove(session.getId());
    	}else{
    		webSocketSet.remove(id);
    	}
    	
    	//webSocketSet.remove(this);  //从set中删除
    	principalMaps.remove(this); 
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }
 
 
	/**
	 * 
	 * @param session
	 * @param error
	 */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
 
    
    /**
     * 群发消息
     * @param warnNoticeInfo
     * @throws IOException
     */
    public void sendMessage(WarnNoticeInfo warnNoticeInfo) throws IOException {
    	//转出json发送
    	session.getBasicRemote().sendText(JacksonUtil.bean2Json(warnNoticeInfo));
    }
 
    
    /**
     * 群发自定义消息(系统主动推送)
     * @param noticeInfo
     * @throws IOException
     */
    public BaseDataResult pushBySys(WarnNoticeInfo noticeInfo) throws IOException {
    	log.info(noticeInfo.toString());
    	boolean flag = false;
        for (Entry<Integer, ConcurrentMap<String, WebSocketServer>> item: webSocketSet.entrySet()) {
        	ConcurrentMap<String, WebSocketServer> value = item.getValue();
        	 for (Entry<String, WebSocketServer> socket: value.entrySet()) {
	        	Integer operatorId = principalMaps.get(item.getKey());
	        	//不向该预警下不是对应的运营商明下的用户推送消息
	        	if(operatorId == null || operatorId.intValue() != noticeInfo.getOperatorId().intValue()){  //
	        		continue;
	        	}
	            try {
	            	socket.getValue().sendMessage(noticeInfo);
	            } catch (IOException e) {
	            	flag = true;
	                continue;
	            }
        	 }
        }
        
        if(flag){
        	return new BaseDataResult(Constans.FAILED, "推送预警信息出现异常!");
        }
        return new BaseDataResult(Constans.FAILED, "推送预警信息成功!");
    }
 
    public static synchronized int getOnlineCount() {
        return onlineCount;
    }
 
    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
 
    public static synchronized void subOnlineCount() {
    	if(WebSocketServer.onlineCount > 0){
    		WebSocketServer.onlineCount--;
    	}
    }
}

3.前端代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
<%-- <jsp:include page="../common/head.jsp"></jsp:include> --%>
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath}/assets/css/layui.css" />
<link rel="stylesheet" type="text/css"
	href="${pageContext.request.contextPath}/assets/css/css.css" />
<script
	src="${pageContext.request.contextPath}/assets/js/jquery-3.2.0.min.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/layui.js"></script>
<script src="${pageContext.request.contextPath}/assets/js/style.js"></script>

<div class="layui-layout layui-layout-admin">
	<div class="layui-header">
	    <!-- 音频 -->
		<audio  autoplay="autoplay" id="auto" src=""></audio>
		<div class="layui-logo">气象站数据采集平台</div>
		<!-- 头部区域(可配合layui已有的水平导航) -->
		<ul class="layui-nav layui-layout-left">
			<shiro:hasPermission name="admin:base">
				<li class="layui-nav-item"><a href="${pageContext.request.contextPath}/admin/index"  target="list">账号管理</a></li>
			</shiro:hasPermission>
			<shiro:hasPermission name="station:base">
				<li class="layui-nav-item"><a href="${pageContext.request.contextPath}/station/index"  target="list">站点管理</a></li>
			</shiro:hasPermission>
			<shiro:hasPermission name="warnInfo:base">
				<li class="layui-nav-item"><a href="${pageContext.request.contextPath}/warn/index" 	target="list">预警管理</a></li>
			</shiro:hasPermission>
			<shiro:hasPermission name="realtime:base">
				<li class="layui-nav-item"><a href="">统计分析</a></li>
			</shiro:hasPermission>
			<shiro:hasPermission name="realtime:base">
				<li class="layui-nav-item layui-this"><a href="${pageContext.request.contextPath}/statis/index"  target="list">实时展示</a></li>
		    </shiro:hasPermission>
		    <shiro:hasPermission name="system:base">
		   		 <li class="layui-nav-item"><a href="${pageContext.request.contextPath}/system/index"  target="list">系统管理</a></li>
			 </shiro:hasPermission>
		</ul>

		<ul class="layui-nav layui-layout-right">
			<li class="layui-nav-item"><a href="javascript:;"> <img
					src="${pageContext.request.contextPath}/images/common/userIcon.jpg" class="layui-nav-img"> ${principal.name}
			</a> <!-- <dl class="layui-nav-child">
                        <dd>
                            <a href="">基本资料</a>
                        </dd>
                        <dd>
                            <a href="">安全设置</a>
                        </dd>
                    </dl> --></li>
			<li class="layui-nav-item"><a onClick="self.parent.location = '${pageContext.request.contextPath}/index/loginout';">注销</a>
			</li>
		</ul>
	</div>
</div>
	<script>
		layui.use('element', function() {
			var element = layui.element;
		});
		$("#changeP").click(function() {
			window.parent.$("#rigth")[0].contentWindow.passwordC();
		})
	</script>
	<script type="text/javascript">
    var websocket = null;
    //判断当前浏览器是否支持WebSocket
    var id = ${principal.id};
    var operatorId = ${principal.operatorId};
    if ('WebSocket' in window) {
        websocket = new WebSocket("ws://192.168.1.161:8080/climate/websocket/"+id+"/"+operatorId);
    }
    else {
        alert('当前浏览器 Not support websocket')
    }

    //连接发生错误的回调方法
    websocket.onerror = function () {
        setMessageInnerHTML("WebSocket连接发生错误");
    };

    //连接成功建立的回调方法
    websocket.onopen = function () {
        setMessageInnerHTML("WebSocket连接成功");
    }

    //接收到消息的回调方法
    websocket.onmessage = function (event) {
    	if(event.data != null){
    		//音频
            var auto = $("#auto");
            auto.attr("src",'../assets/audio/6124.wav');              
    	}
    	var obj = JSON.parse(event.data);
    	console.log("test:"+obj.id);
        setMessageInnerHTML(event.data);
    }

    //连接关闭的回调方法
    websocket.onclose = function () {
        setMessageInnerHTML("WebSocket连接关闭");
    }

    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
        closeWebSocket();
    }

    //将消息显示在网页上
    function setMessageInnerHTML(innerHTML) {
        //document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }

    //发送消息
    function send() {
        var message = document.getElementById('text').value;
        websocket.send(message);
    }
</script>
</head>

        <!-- 音频 -->
        <audio  autoplay="autoplay" id="auto" src=""></audio>  

package com.cloudtech.web.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
 
}

上面这句话是后台推送后,声音提醒

websocket坑点1:ws://192.168.1.161:8080/climate/websocket

项目访问的地址需要跟websocket一样,不然会有问题

猜你喜欢

转载自blog.csdn.net/qq_16855077/article/details/82858214
今日推荐