tomcat的websocket实现

环境
jdk1.8、tomcat8、浏览器谷歌77、IE11
websocket的实现有2种方式,一种为tomcat的websocket,比较简单,tomcat要求7以上,低版本浏览器可能有兼容问题,未测试。另外一种为spring整合websocket,spring的版本要求4.x以上,可以通过socketjs实现低版本浏览器兼容,参考地址:https://blog.csdn.net/weixin_44262390/article/details/100988545
pom.xml

<!-- webSocket -->
	<dependency>
		<groupId>javax.websocket</groupId>
		<artifactId>javax.websocket-api</artifactId>
		<version>1.1</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>javax</groupId>
		<artifactId>javaee-api</artifactId>
		<version>7.0</version>
	</dependency>

websocket.js
前端脚本

var wb;

//脚本入口
$(function () {
    wb_connect();
});

/**
 * 连接 websocket
 * @param func onopen要执行的函数,可以为空
 */
function wb_connect() {
    wb = new WebSocket("ws://"+window.location.host+"/xmm/test");
    //j接收服务端主动推送消息
    wb.onmessage = function (event) {
        if(event==""||event==null)
            return;
        }
        if(event.data == null || event.data == ""){
            return;
        }
        var keys= Object.keys(JSON.parse(event.data));
        $.each(keys,function(index,item){
            if(item=="xx"){
             
            }
        })  
    }
    wb.onopen = function () {
        // 开启心跳
        ws_heart();
    };
    wb.onerror = function (e) {
    	console.log("webSocket发生错误");
    };
    wb.onclose = function (e) {
    	console.log("webSocket关闭");
    };
}



/**
 * 根据连接状态单线程连接 websocket
 * @param func onopen要执行的函数,可以为空
 */
function wb_execute() {
    //console.log("ws状态是:" + ws.readyState);
    if (wb.readyState == 0) {
        //连接中
        var _old$open = wb.onopen;
        wb.onopen = function (e) {
            // 原本 onopen 里的代码先执行完毕
            _old$open.apply(this, arguments);
        };
    } else if (wb.readyState == 1) {
    	//连接正常,暂未处理
    } else if (wb.readyState == 2) {
        //连接正在关闭,需要重新连接
        var _old$close = wb.onclose;
        wb.onclose = function (e) {
            //原本 onclose 里的代码先执行完毕
            _old$close.apply(this, arguments);
            wb_connect();
        };
    } else if (wb.readyState == 3) {
        //连接已关闭或者没有链接成功,需要重新连接
        wb_connect();
    }
}

var wb_heart_i = null;

/**
 * websocket 每1分钟发一次心跳 判断连接是否正常
 */
function wb_heart() {
    if (wb_heart_i) clearInterval(wb_heart_i);
    wb_heart_i = setInterval(function () {
        wb_execute();
    }, 10000);
}

后端实现

import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.http.HttpSession;
import javax.websocket.EndpointConfig;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.common.EmptyUtil;
import com.dao.systemmanager.domain.SysUser;
//configurator = HttpSessionConfigurator.class 为了获取Httpsession
@ServerEndpoint(value = "/test", configurator = HttpSessionConfigurator.class)
public class WebServer {
	private static ConcurrentHashMap<String, WebServer> webSocketSet = new ConcurrentHashMap<>();
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    private HttpSession httpSession;
    private String id = "";
    
    public HttpSession getHttpSession() {
		return httpSession;
	}

	public void setHttpSession(HttpSession httpSession) {
		this.httpSession = httpSession;
	}

	@OnOpen
    public void onOpen(Session session,EndpointConfig config) {
    	httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
    	SysUser sysUser = (SysUser) httpSession.getAttribute("user");
    	if (EmptyUtil.isEmpty(sysUser)) {
			return;
		}
        this.session = session;
        webSocketSet.put(String.valueOf(sysUser.getId()), this);//加入set中
        WebManager.add(this);
    }

	public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);  //同步方法
    }
	
	/**
     * 发送信息给指定ID用户,如果用户不在线则返回不在线信息给自己
     * @param message
     * @param sendUserId
     * @throws IOException
     */
    public void sendtoUser(String message,String sendUserId) throws IOException {
        if (webSocketSet.get(sendUserId) != null) {
            webSocketSet.get(sendUserId).sendMessage(message);
        } else {
            //如果用户不在线则返回不在线信息给自己
            sendtoUser("当前用户不在线",id);
        }
    }

    @OnClose
    public void onClose() {
        WebManager.remove(this);
    }

    @OnMessage
    public void onMessage(String message, Session session) {
    	System.out.print(message);
    }

    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("webSocket发生错误");
    }
}
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class WebManager {

    public static List<WebServer> list = Collections.synchronizedList(new ArrayList<WebServer>());
	//广播--发给所有用户
    public static void broadCast(String message) {
        for (WebServer ws : list) {
            try {
                ws.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //发给指定用户
    public static void msgPushToUser(String message,String sendUserId) {
        for (WebServer ws : list) {
            try {
                ws.sendtoUser(message, sendUserId);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void add(WebServer server) {
        list.add(server);

    }

    public static void remove(WebServer server) {
        list.remove(server);
    }
}

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
// 为了获取Httpsession
public class HttpSessionConfigurator extends Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
    }
}

业务实现

//短信消息生成完成后查询短信消息与系统公告消息未读数量,推送到前端
List<WebServer> list = WebManager.list;
if (EmptyUtil.isNotEmpty(list)) {
	for(WebServer server : list){
		User user = (User)server.getHttpSession().getAttribute("user");
		if (EmptyUtil.isEmpty(user )) {
			logger.info("消息推送失败,当前登录用户信息为空,请重检查新登录");
			return;
		}
		HashMap<String, Object> map = new HashMap<>();
		map .put("xx", "xx");
		//WebManager.broadCast(JSONObject.toJSONString(map));//广播
		//发送消息给指定用户
		WebManager.msgPushToUser(JSONObject.toJSONString(map),"");
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值