webSocket配置类
import javax.websocket.Endpoint; import javax.websocket.server.ServerApplicationConfig; import javax.websocket.server.ServerEndpointConfig; import java.util.Set; /** * @author baozi * @title webSocket服务配置类 * @date 2018/4/14 10:45 * @description */ public class WebSocketConfig implements ServerApplicationConfig { /* * 1. getAnnotatedEndpointClasses * 2. getEndpointConfigs * * 上面的两个方法都是用来注册 webSocket的。 只不过注册的方式不同。 1方法是 注解的方式 * 2方法是 接口的方式 * * 显然 注解的方式更加的 灵活简单。 接口的方式更加的传统,严谨。 * * (non-Javadoc) * @see javax.websocket.server.ServerApplicationConfig#getAnnotatedEndpointClasses(java.util.Set) */ public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> arg0) { // argo.size();是去扫描注解@ServerEndpoint的类的个数 System.out.println("正在扫描所有的webSocket服务!!!" + arg0.size()); return arg0; } public Set<ServerEndpointConfig> getEndpointConfigs( Set<Class<? extends Endpoint>> arg0) { // TODO Auto-generated method stub return null; } }
首先定义一个WebSocket服务器
import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.io.IOException; /** * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端, * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
* session.getQueryString()拿到的是,页面连接服务器时的?后面的值 (ip=xxx.xxx.xxx.xxx)
* var target = "ws://localhost:8080/websocket?ip=" + ip; */ @ServerEndpoint("/websocket") public class MyWebSocket { /** * 与某个客户端的连接会话,需要通过它来给客户端发送数据 */ private Session session; /** * 连接建立成功调用的方法 * Session是webSocket的回话,一个session 代表一个通信会话 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */ @OnOpen public void onOpen(Session session) { this.session = session; System.out.println("sessionID:" + session.getId()); WebSocketMapUtil.put(session.getQueryString().split("=")[1],session); } /** 连接关闭调用的方法 */ @OnClose public void onClose() { //从map中删除 WebSocketMapUtil.remove(session.getQueryString().split("=")[1]); System.out.println("连接关闭"); } /** * 发生错误时调用 * @param session * @param error */ @OnError public void onError(Session session, Throwable error){ error.printStackTrace(); } /** * 发送消息方法。 * @param message * @throws IOException */ public void sendMessage(String ip,String message) throws IOException{ String trim = ip.trim(); if(trim != null && WebSocketMapUtil.getValues() != null){ WebSocketMapUtil.get(trim).getBasicRemote().sendText(message); } } }
服务器的工具类
import javax.websocket.Session; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * @author baozi * @title * @date 2018/4/14 9:01 * @description */ public class WebSocketMapUtil { public static ConcurrentMap<String, Session> webSocketMap = new ConcurrentHashMap<>(); public static void put(String key, Session session){ webSocketMap.put(key, session); } public static Session get(String key){ return webSocketMap.get(key.trim()); } public static void remove(String key){ webSocketMap.remove(key); } public static Collection<Session> getValues(){ return webSocketMap.values(); } }
服务端发送客户端
/** * webSocket发送消息给客户端 start */ MyWebSocket myWebSocket = new MyWebSocket(); ClassFlow classFlow = new ClassFlow(); classFlow.setIntNum(22); classFlow.setOutNum(12); try { classFlow.setPeople(people); myWebSocket.sendMessage(ip,new Gson().toJson(classFlow)); /** * webSocket发送消息给客户端 end */
页面的逻辑
<%@ page language="java" import="java.util.*" pageEncoding="Utf-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!doctype html> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <html lang="en"> <head> <title></title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Pragma" content="no-cache" /> <meta http-equiv="Cache-Control" content="no-cache, must-revalidate" /> <meta http-equiv="Expires" content="0" /> <script> document.write("<link type='text/css' href='<%=basePath %>module/css/video/demo.css?version=" + new Date().getTime() + "' rel='stylesheet' />"); </script> <link href="<%=basePath %>media/assets/css/bootstrap.css" rel="stylesheet"> </head> <style> .wrapper { margin-top:70px !important; } </style> <body> <section class="wrapper"> <div class="row mt" id="classDiv"> <c:forEach items="${classrooms}" var="c"> <div class="col-md-2" style="cursor:pointer;height: 100px;background: gray;text-align: center;padding-top: 30px;margin: 10px;" onclick="ws_init('${c.ips}')"> <div>${c.name}</div> <div>${c.num}</div> </div> </c:forEach> </div> <div class="left" > <div id="videoLeft" style="display: none"> <div id="divPlugin" class="plugin"></div> <input type="button" class="btn" value="开始预览" onclick="clickStartRealPlay();" /> </div> <fieldset class="login" style="display: none"> <legend>登录</legend> <table cellpadding="0" cellspacing="3" border="0"> <tr> <td class="tt">IP地址</td> <td><input id="loginip" type="text" class="txt" value="192.168.5.16" /></td> <td class="tt">端口号</td> <td><input id="port" type="text" class="txt" value="80" /></td> </tr> <tr> <td class="tt">用户名</td> <td><input id="username" type="text" class="txt" value="admin" /></td> <td class="tt">密码</td> <td><input id="password" type="password" class="txt" value="hk123456" /></td> </tr> <tr> <td class="tt">设备端口</td> <td colspan="2"><input id="deviceport" type="text" class="txt" value="8000" />(可选参数)</td> <td> 窗口分割数 <select class="sel2" onchange="changeWndNum(this.value);"> <option value="1" selected>1x1</option> <option value="2">2x2</option> <option value="3">3x3</option> <option value="4">4x4</option> </select> </td> </tr> <tr> <td colspan="4"> <input type="button" class="btn" id="loginBtn" value="登录" onclick="clickLogin();" /> <input type="button" class="btn" value="退出" onclick="clickLogout();" /> <input type="button" class="btn2" value="获取基本信息" onclick="clickGetDeviceInfo();" /> </td> </tr> <tr> <td class="tt">已登录设备</td> <td> <select id="ip" class="sel" onchange="getChannelInfo();"></select> </td> <td class="tt">通道列表</td> <td> <select id="channels" class="sel"></select> </td> </tr> </table> </fieldset> </div> <div class="left"> <fieldset class="preview" style="display: none"> <legend>预览</legend> <table cellpadding="0" cellspacing="3" border="0"> <tr> <td class="tt">码流类型</td> <td> <select id="streamtype" class="sel"> <option value="1">主码流</option> <option value="2">子码流</option> <option value="3">第三码流</option> <option value="4">转码码流</option> </select> </td> <td> <input type="button" class="btn" value="开始预览" id="realPlayBtn" onclick="clickStartRealPlay();" /> <input type="button" class="btn" value="停止预览" onclick="clickStopRealPlay();" /> </td> </tr> <tr> <td class="tt">音量</td> <td> <input type="text" id="volume" class="txt" value="50" maxlength="3" /> <input type="button" class="btn" value="设置" onclick="clickSetVolume();" />(范围:0~100) </td> <td> <input type="button" class="btn" value="打开声音" onclick="clickOpenSound();" /> <input type="button" class="btn" value="关闭声音" onclick="clickCloseSound();" /> </td> </tr> <tr> <td class="tt">对讲通道</td> <td> <select id="audiochannels" class="sel"> </select> <input type="button" class="btn" value="获取通道" onclick="clickGetAudioInfo();" /> </td> <td> <input type="button" class="btn" value="开始对讲" onclick="clickStartVoiceTalk();" /> <input type="button" class="btn" value="停止对讲" onclick="clickStopVoiceTalk();" /> </td> </tr> <tr> <td colspan="3"> <input type="button" class="btn" value="抓图" onclick="clickCapturePic();" /> <input type="button" class="btn" value="开始录像" onclick="clickStartRecord();" /> <input type="button" class="btn" value="停止录像" onclick="clickStopRecord();" /> </td> </tr> <tr> <td colspan="3"> <input type="button" class="btn2" value="启用电子放大" onclick="clickEnableEZoom();" /> <input type="button" class="btn2" value="禁用电子放大" onclick="clickDisableEZoom();" /> <input type="button" class="btn2" value="启用3D放大" onclick="clickEnable3DZoom();" /> <input type="button" class="btn2" value="禁用3D放大" onclick="clickDisable3DZoom();" /> <input type="button" class="btn" value="全屏" onclick="clickFullScreen();" /> </td> </tr> </table> </fieldset> </div> <div class="left" id="videoInfo" style="display:none;margin-left:50px"> <div>进入人数:<span id="intNum"></span></div> <div>离开人数:<span id="outNum"></span></div> <div>当前人数:<span id="people"></span></div> </div> </section> </body> <script src="<%=basePath %>module/js/jquery-1.7.1.min.js"></script> <script src="<%=basePath %>module/js/video/webVideoCtrl.js"></script> <script src="<%=basePath %>module/js/video/demo.js"></script> <script type="text/javascript">
var ws;//一个ws对象就是一个通信管道 /** * 点击班级触发 视频显示 * @param ip */ function ws_init(ip) { //视频的界面 $("#videoLeft").show(); var target = "ws://localhost:8080/websocket?ip=" + ip; //浏览器兼容性的判断 if ('WebSocket' in window) { ws = new WebSocket(target); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(target); } else { alert('WebSocket is not supported by this browser.'); return; } //信息展示 $("#videoInfo").show(); //触发设备的登录 $("#loginBtn").click(); getChannelInfo(); // window.setTimeout(document.getElementById("loginBtn").click(), 1000); //窗口默认1个 changeWndNum(1); //触发视频预览 // $("#realPlayBtn").click(); // window.setTimeout(clickStartRealPlay(), 1000); clickStartRealPlay(); // window.setTimeout($("#realPlayBtn").click(), 1000); //页面值的回显 ws.onmessage = function (evt) { var jsonObj = eval('(' + evt.data + ')'); console.log(jsonObj); $("#intNum").text(jsonObj.intNum); $("#outNum").text(jsonObj.outNum); }; }
</script> </html>