zoukankan      html  css  js  c++  java
  • WebSocket前后端实现


    websocket.jsp

    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@include file="/common/common-uplan.jsp"%>
    <script>
    var wsUri ="ws://localhost:8080/xbnet-product-web/websocket?username=${user.name}&userId=${user.operatorId}"; 
    
    //判断浏览器是否支持websocket
    if(window.WebSocket){
    	//创建websocket连接
    	websocket = new WebSocket(wsUri);
        console.log('This browser supports WebSocket');
    }else{
        console.log('This browser does not supports WebSocket');
    }
    
    //连接成功建立的回调方法
    websocket.onopen = function() { 
    	writeToScreen("webSocket连接成功"); 
    }; 
    
    //连接关闭的回调方法
     websocket.onclose = function() { 
    	 writeToScreen("webSocket连接关闭");
     }; 
        
    //接收到消息的回调方法
    websocket.onmessage = function(event) { 
    	writeToScreen(event.data);
    }; 
    
    //连接发生错误的回调方法
    websocket.onerror = function() { 
    	writeToScreen("WebSocket连接发生错误");
    }; 
      
    //关闭WebSocket连接
    function closeWebSocket() {
        websocket.close();
    }  
    
    function doSend() { 
    	var text = $("#text") .val();
    	var users = $('input:checkbox:checked');
    	var touser = "";
    	if (users.length  == 0){
    		alert("请选择发送人!");
    		return;
    	} else{
    		for (var i = 0; i < users.length; i++){
    			touser += users[i].value + "|";
    		}
    	}
    	if (text != "" && text != undefined && text != null){
    	    var obj = null;
    	    obj = {
    	            toUser:touser,  
    	            fromUser:"${user.operatorId}",  
    	            msg:text
    	    };
    	    obj = JSON.stringify(obj);
    	    websocket.send(obj);
    	    $("#text") .val("");
    	}
    }  
    
    function writeToScreen(message) { 
    	var output = document.getElementById('output');
        var pre = document.createElement("p"); 
        pre.style.wordWrap = "break-word"; 
        pre.innerHTML = message; 
        output.appendChild(pre); 
    }  
    
    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
    	closeWebSocket();
    }
    
    </script>
    <div id="main">
    	<div id="left" style=" 350px;height: 280px;float: left;">
    	    <!-- 消息显示栏 -->
    	    <div id="output" style=" 350px;height: 240px"></div><hr/>
    	    
    	    <!-- 消息发送栏 -->
    	    <input id="text" type="text"/>
    	    <button onclick="doSend()">发送消息</button>
    	</div>
    	
    	
    	<!-- 用户列表 -->
        <div class="up-form-group up-col-sm-24" style=" 100px;height: 280px;float: right;border-left:1px solid gray">
    	     <c:forEach items="${operator }" var="rowdata" varStatus="status">
    		     <div class="up-col-sm-24">
    		         <label class="u_check">
    		             <input id="" value="${rowdata.operatorId }" type="checkbox">
    		             <i class="up-text-primary icon-u-check-empty"></i>${rowdata.name }
    		         </label>
    		     </div>
    	     </c:forEach>
    	</div>
    </div>  
    
    


    WebSocket.java

    
    package com.eshore.security.controller;
    
    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnError;
    import javax.websocket.OnMessage;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    import com.alibaba.fastjson.JSON;
    
    /**
     * webSocket
     * @author renb
     * @creatDate 2018年2月22日
     */
     // @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
     //               注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
    @ServerEndpoint("/websocket")
    public class WebSocket {
    	// 静态变量,用来记录当前在线连接数。
    	private static int onlineCount = 0;
    
    	// concurrent包的线程安全Map,用来存放每个客户端对应的回话信息。
    	private static ConcurrentMap<String, Session> webSocketMap = 
    			new ConcurrentHashMap<String, Session>();
    	private String userName; //当前用户
    	private String userId; //当前用户id,作为webSocketMap科key
    	/**
    	 * 连接建立成功调用的方法
    	 * 
    	 * @param session
    	 *            可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
    	 */
    	@OnOpen
    	public void onOpen(Session session) {
    		String str = session.getQueryString(); //可以得到ws://路径?后面的所有字符串  
    		userName = str.split("&")[0].split("=")[1]; 
    		userId = str.split("&")[1].split("=")[1];
        	try {
    			userName = URLDecoder.decode(userName, "utf-8");
    		} catch (UnsupportedEncodingException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}  
    		webSocketMap.put(userId, session); // 加入map中
    		addOnlineCount(); // 在线数加1
    		System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    	}
    
    	/**
    	 * 连接关闭调用的方法
    	 */
    	@OnClose
    	public void onClose() {
    		webSocketMap.remove(userId); // 从map中删除
    		subOnlineCount(); // 在线数减1
    		System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
    	}
    
    	/**
    	 * 收到客户端消息后调用的方法
    	 * 
    	 * @param message
    	 *            客户端发送过来的消息
    	 * @param session
    	 *            可选的参数
    	 */
    	@SuppressWarnings("rawtypes")
    	@OnMessage
    	public void onMessage(String message, Session session) {
    		System.out.println(userName + ":" + message);
    		Map maps = (Map) JSON.parse(message);
    		Map<String, String> resultMap = new HashMap<String, String>();
    		for (Object map : maps.entrySet()) {  
    			String  key = (String) ((Map.Entry) map).getKey();
    			String value = (String) ((Map.Entry) map).getValue();
    			resultMap.put(key, value);
            } 
    		String msg = userName + ":" + resultMap.get("msg");
    		String toUsers = resultMap.get("toUser");
    		String fromUser = resultMap.get("fromUser");
    		String[] users = toUsers.split("\|");
    		try {
    			webSocketMap.get(fromUser).getBasicRemote().sendText(msg);
    			Set<String> set = webSocketMap.keySet();
    			List<String> userList = new ArrayList<String>();
    			for (String str : set) {
    				userList.add(str);
    			}
    			if (users.length > 0) {
    				for (int i = 0; i < users.length; i++) {
    					if (userList.contains(users[i])) {
    						webSocketMap.get(users[i]).getBasicRemote().sendText(msg);
    					}
    				}
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 发生错误时调用
    	 * 
    	 * @param session 会话
    	 * @param error 异常
    	 */
    	@OnError
    	public void onError(Session session, Throwable error) {
    		System.out.println("发生错误");
    		error.printStackTrace();
    	}	public static synchronized int getOnlineCount() {
    		return onlineCount;
    	}
    
    	/**
    	 * 
    	 * @creatUser renb
    	 * @creatDate 2018年2月22日
    	 *
    	 */
    	public static synchronized void addOnlineCount() {
    		WebSocket.onlineCount++;
    	}
    
    	/**
    	 * 
    	 * @creatUser renb
    	 * @creatDate 2018年2月22日
    	 *
    	 */
    	public static synchronized void subOnlineCount() {
    		WebSocket.onlineCount--;
    	}
    
    	
    }
    
    
  • 相关阅读:
    从源码解读Spring如何解决bean循环依赖
    前后端分离下用jwt做用户认证
    断点调试获取程序当前位置的运行结果
    Win10安装MySQL8压缩包版
    IDEA实用快捷键推荐
    多平台博客发布工具OpenWrite的使用
    Tomcat部署多个war包
    从储值卡(会员卡)充值业务看分布式事务的设计
    再谈 PHP 未来之路
    Swoole 实战:MySQL 查询器的实现(协程连接池版)
  • 原文地址:https://www.cnblogs.com/lovellll/p/10213901.html
Copyright © 2011-2022 走看看