注意:websocket只有tomcat7.4.5以上才支持
可以用google插件来测试
所需要jar包
javax
javaee-api
7.0
provided
session队列:
package com.common.pojo.websocket;
import lombok.Data;
import javax.websocket.Session;
import java.io.Serializable;
/**
* websocketsession实体类
*
* @author nachuan
* @create 2019-09-06 10:21
*/
@Data
public class WebsocketSessionDto implements Serializable {
/**sessionid*/
private String sessionId;
/**websocket的session*/
private Session session;
/**用户id*/
private String userId;
/**心跳时间*/
private long heartbeatTime;
/**组id*/
private String groupId;
/**最后链接时间*/
private long lastConTime;
}
任务队列
package com.common.pojo.websocket;
import lombok.Data;
import org.junit.Test;
import java.io.Serializable;
/**
* websocket返回值
*
* @author nachuan
* @create 2019-09-16 14:50
*/
@Data
public class ResWsTask implements Serializable {
/**type默认0 普通消息 1,心跳*/
private int methodType = 0;
/**返回结果 */
private WebSocketTask task;
}
package com.common.pojo.websocket;
import com.common.utils.jsonUtils.MyFastJsonUtils;
import com.common.utils.randomutils.MyUUIDutils;
import com.skyvis.websocket.ResWsTask;
import lombok.Data;
import java.io.Serializable;
/**
* websocket失败任务
*
* @author nachuan
* @create 2019-09-06 13:29
*/
@Data
public class WebSocketTask implements Serializable {
/**任务id*/
private String taskId;
/**消息*/
private String msg;
/**发送时间*/
private long startTime;
/**用户id*/
private String userId;
/**组id*/
private String groupId;
/**任务编号*/
private Integer taskNum;
public static void main(String[] args) {
ResWsTask resWsTask = new ResWsTask();
// resWsTask.setType(0);
WebSocketTask task = new WebSocketTask();
task.setTaskId(MyUUIDutils.getTimeUuid());
task.setMsg("测试消息");
task.setStartTime(System.currentTimeMillis());
task.setUserId(MyUUIDutils.getTimeUuid());
task.setGroupId(MyUUIDutils.getTimeUuid());
task.setTaskNum(100001);
resWsTask.setTask(task);
System.out.println(MyFastJsonUtils.obj2JsonStr(resWsTask));
}
}
websocket服务(单机版):
import com.common.pojo.websocket.WebSocketTask;
import com.common.pojo.websocket.WebsocketSessionDto;
import com.common.utils.dailyutils.EmptyUtils;
import com.common.utils.jsonUtils.MyFastJsonUtils;
import com.common.utils.log.MyLogUtils;
import com.common.utils.randomutils.MyUUIDutils;
import com.common.utils.timeUtils.MyTimeUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
/**
* websocket多连
*
* @author nachuan
* @create 2019-09-08 15:15
*/
@ServerEndpoint("/webSocketService/{uid}")
@Component
public class MyWebSocketMore implements Serializable {
private static final Logger log = MyLogUtils.getSlf4jLogger(MyWebSocketMore.class);
/**session存储集合*/
private static List sessionList = new ArrayList();
/**任务队列*/
private static List taskList = new ArrayList();
/**每个session访问的次数*/
private static HashMap sessionUserInCountMap = new HashMap<>();
@Scheduled(cron = "*/30 * * * * ?")
public void updateData(){
log.info("清理sessionList详情:{}",sessionList);
if (EmptyUtils.isNotEmpty(sessionList)) {
for (int i = 0; i < sessionList.size(); i++) {
if (!sessionList.get(i).getSession().isOpen()) {
removeSession(sessionList.get(i).getSession());
log.info("清理无用的session ,sessionId={},userId={}",sessionList.get(i).getSessionId(),sessionList.get(i).getUserId());
}
}
}
}
@Scheduled(cron = "*/5 * * * * ?")
public void sendTask(){
if (EmptyUtils.isNotEmpty(taskList)) {
for (int i = 0; i < taskList.size(); i++) {
WebSocketTask task = taskList.get(i);
log.info("队列任务====开始发送-接收人:{},消息:{},任务时间={},taskId={}",task.getUserId(),task.getMsg(), MyTimeUtils.fmttime(task.getStartTime()),task.getTaskId());
for (WebsocketSessionDto websocketSessionDto : sessionList) {
if (Objects.equals(task.getUserId(), websocketSessionDto.getUserId())) {
try {
boolean isOpen = websocketSessionDto.getSession().isOpen();
if (isOpen) {
websocketSessionDto.getSession().getBasicRemote().sendText(MyFastJsonUtils.obj2JsonStr(task));
log.info("队列任务-正在发送====开始发送-接收人:{},消息:{},任务时间={},taskId={}",task.getUserId(),task.getMsg(), MyTimeUtils.fmttime(task.getStartTime()),task.getTaskId());
}
} catch (IOException e) {
log.info("队列任务=====失败任务数量:{},任务内容:{}",taskList.size(),taskList);
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
}
}
@OnOpen
public void onOpen (Session session, @PathParam(value = "uid")String uid ) {
log.info("建立链接:sessinid={},userid={},sessionList={},sessionList.size={},groupId={}" ,
session.getId(), uid,sessionList.toString(),sessionList.size());
addWebSocketSession(session, uid);
log.info("建立链接后:sessionList.size={},详情={}" ,sessionList.size(), sessionList);
}
@OnClose
public void onClose(Session session) {
log.info("断开连接的sessionid ={} " , session.getId());
removeSession(session);
}
/**
* 移除无用的session
* @param session
*/
private void removeSession(Session session) {
if (EmptyUtils.isNotEmpty(sessionList)) {
for (int i = 0; i < sessionList.size(); i++) {
if (Objects.equals(session.getId(), sessionList.get(i).getSessionId())) {
sessionList.remove(sessionList.get(i));
log.info("移除session后sessionid={}",session.getId());
log.info("移除后的sessionList.size={},sessionList={}",sessionList.size(),sessionList);
try {
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 发送消息给某个人
* @param userId
* @param msg
*/
public void sendMsgTosb(String userId,String groupId,Integer taskNum ,String msg) {
WebSocketTask task = new WebSocketTask();
task.setMsg(msg);
task.setTaskId(MyUUIDutils.getTimeUuid());
task.setStartTime(System.currentTimeMillis());
task.setUserId(userId);
task.setGroupId(groupId);
task.setTaskNum(taskNum);
log.info("开始发送-接收人:{},消息:{}",userId,msg);
Map userMsgMap = new HashMap<>();
for (WebsocketSessionDto websocketSessionDto : sessionList) {
// if (Objects.equals(userId, websocketSessionDto.getUserId()) && websocketSessionDto.getSession().isOpen() && !Objects.equals(userMsgMap.get(userId),msg)) {
if (Objects.equals(userId, websocketSessionDto.getUserId()) && websocketSessionDto.getSession().isOpen() ) {
try {
//如果不包含
websocketSessionDto.getSession().getBasicRemote().sendText(MyFastJsonUtils.obj2JsonStr(task));
// userMsgMap.put(userId,msg);
log.info("发送成功------接收人:{},消息:{}",userId,msg);
} catch (IOException e) {
e.printStackTrace();
log.info("失败任务数量:{},任务内容:{}",taskList.size(),taskList);
}
taskList.add(task);
}else {
continue;
}
}
}
@OnMessage
public void onMessage(String message,Session session) {
log.info("收到消息: msg={},sessionid={},sessionSize={},sessionList详情={}" ,message,session.getId(),sessionList.size(),sessionList);
String uid= "";
String taskId = "";
if (message.contains("userId") && message.contains("taskId")) {
Map
websocket服务,集群版
(websocket无法注入redisTemple所引用的redis工具类:https://nachuan.blog.csdn.net/article/details/96644466
map排序工具类: https://nachuan.blog.csdn.net/article/details/100898502)
import com.common.pojo.websocket.ResWsTask;
import com.common.pojo.websocket.WebSocketTask;
import com.common.pojo.websocket.WebsocketSessionDto;
import com.common.utils.dailyutils.EmptyUtils;
import com.common.utils.jsonUtils.MyFastJsonUtils;
import com.common.utils.log.MyLogUtils;
import com.common.utils.map.JavaMapUtils;
import com.common.utils.otherUtils.RedisAPI;
import com.common.utils.timeUtils.MyTimeUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* websocket多连
*
* @author nachuan
* @create 2019-09-08 15:15
*/
@ServerEndpoint("/webSocketService/{uid}")
@Component
public class MyWebSocketMore implements Serializable {
private static final Logger log = MyLogUtils.getSlf4jLogger(MyWebSocketMore.class);
/**session存储集合*/
private static final List sessionList = new ArrayList();
/**任务key*/
private static final String taskKey = "websocketTaskKey";
/**每个session访问的次数*/
private static HashMap sessionUserInCountMap = new HashMap<>();
/**避免并发情况下,一个session同时被占用发送消息*/
private static final Lock lock = new ReentrantLock();
@Scheduled(cron = "*/30 * * * * ?")
public void updateData(){
// log.info("清理sessionList详情:{}",sessionList);
if (EmptyUtils.isNotEmpty(sessionList)) {
for (int i = 0; i < sessionList.size(); i++) {
if (!sessionList.get(i).getSession().isOpen()) {
removeSession(sessionList.get(i).getSession());
// log.info("清理无用的session ,sessionId={},userId={}",sessionList.get(i).getSessionId(),sessionList.get(i).getUserId());
}
}
}
}
@Scheduled(cron = "*/10 * * * * ?")
public void sendTask(){
Jedis jedis = RedisAPI.getJedis();
jedis.select(MyWebSocketEnum.WS_SELECT_DATABASE);
Map valueMap = jedis.hgetAll(taskKey);
if (EmptyUtils.isNotEmpty(valueMap.values())) {
Map resultMap = JavaMapUtils.sortMap(valueMap);
Collection taskCollection = resultMap.values();
Object[] taskList = taskCollection.toArray();
if (EmptyUtils.isNotEmpty(taskList)) {
for (int i = 0; i < taskList.length; i++) {
ResWsTask resWsTask = MyFastJsonUtils.strToBean(taskList[i].toString(), ResWsTask.class);
WebSocketTask task = resWsTask.getTask();
//超过24小时的任务直接删除
log.info("任务时间差:{},任务id={}",System.currentTimeMillis() - task.getStartTime(),task.getTaskId());
if (System.currentTimeMillis() - task.getStartTime() > 24 * 60 * 60 * 1000) {
jedis.hdel(taskKey,task.getTaskId());
}
log.info("队列任务====开始发送-接收人:{},消息:{},任务时间={},taskId={}",task.getUserId(),task.getMsg(), MyTimeUtils.fmttime(task.getStartTime()),task.getTaskId());
for (WebsocketSessionDto websocketSessionDto : sessionList) {
if (Objects.equals(task.getUserId(), websocketSessionDto.getUserId())) {
try {
Session session = websocketSessionDto.getSession();
sendWsText(session,resWsTask);
log.info("队列任务-正在发送====开始发送-接收人:{},消息:{},任务时间={},taskId={}",task.getUserId(),task.getMsg(), MyTimeUtils.fmttime(task.getStartTime()),task.getTaskId());
} catch (IOException e) {
log.info("队列任务=====失败任务数量:{},任务内容:{}",taskList.length,taskList);
e.printStackTrace();
throw new RuntimeException(e);
}
}
}
}
}
}
jedis.close();
}
/**
* 发送websocket消息
* @param session
* @param resWsTask
* @throws IOException
*/
private void sendWsText(Session session,ResWsTask resWsTask) throws IOException {
lock.lock();
if (session.isOpen()) {
session.getBasicRemote().sendText(MyFastJsonUtils.obj2JsonStr(resWsTask));
}
lock.unlock();
}
@OnOpen
public void onOpen (Session session, @PathParam(value = "uid")String uid ) {
log.info("建立链接:sessinid={},userid={},sessionList={},sessionList.size={},groupId={}" ,
session.getId(), uid,sessionList.toString(),sessionList.size());
addWebSocketSession(session, uid);
log.info("建立链接后:sessionList.size={},详情={}" ,sessionList.size(), sessionList);
}
@OnClose
public void onClose(Session session) {
log.info("断开连接的sessionid ={} " , session.getId());
removeSession(session);
}
/**
* 移除无用的session
* @param session
*/
private void removeSession(Session session) {
if (EmptyUtils.isNotEmpty(sessionList)) {
for (int i = 0; i < sessionList.size(); i++) {
if (Objects.equals(session.getId(), sessionList.get(i).getSessionId())) {
sessionList.remove(sessionList.get(i));
log.info("移除session后sessionid={}",session.getId());
log.info("移除后的sessionList.size={},sessionList={}",sessionList.size(),sessionList);
try {
session.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 发送消息给某个人
* @param userId
* @param msg
*/
public void sendMsgTosb(String userId,String groupId,Integer taskNum ,String msg) {
WebSocketTask task = new WebSocketTask();
ResWsTask resWsTask = new ResWsTask();
task.setMsg(msg);
task.setTaskId(System.currentTimeMillis()+"");
task.setStartTime(System.currentTimeMillis());
task.setUserId(userId);
task.setGroupId(groupId);
task.setTaskNum(taskNum);
Jedis jedis = RedisAPI.getJedis();
jedis.select(MyWebSocketEnum.WS_SELECT_DATABASE);
log.info("开始发送-接收人:{},消息:{}",userId,msg);
resWsTask.setTask(task);
getSessionAndSendMsg(userId, msg, resWsTask, jedis);
jedis.close();
}
/**
* 获取session并发送消息
* @param userId
* @param msg
* @param task
* @param jedis
*/
private void getSessionAndSendMsg(String userId, String msg, ResWsTask task, Jedis jedis) {
for (WebsocketSessionDto websocketSessionDto : sessionList) {
if (Objects.equals(userId, websocketSessionDto.getUserId()) && websocketSessionDto.getSession().isOpen()) {
try {
//如果不包含
Session session = websocketSessionDto.getSession();
sendWsText(session,task);
log.info("发送成功------接收人:{},消息:{}", userId, msg);
} catch (IOException e) {
e.printStackTrace();
log.info("失败任务数,任务内容:{}", task);
}
jedis.hset(taskKey, task.getTask().getTaskId(), MyFastJsonUtils.obj2JsonStr(task));
} else {
continue;
}
}
}
/**
* 发送消息给某群组
* @param userIdList 接受人的id集合
* @param groupId 组id
* @param taskNum 任务编号
* @param msg 消息
*/
public void sendMsgToGroup(ListuserIdList, String groupId,Integer taskNum ,String msg) {
Jedis jedis = RedisAPI.getJedis();
jedis.select(MyWebSocketEnum.WS_SELECT_DATABASE);
for (String userId : userIdList) {
ResWsTask resWsTask = new ResWsTask();
WebSocketTask task = new WebSocketTask();
task.setMsg(msg);
task.setTaskId(System.currentTimeMillis()+"");
task.setStartTime(System.currentTimeMillis());
task.setUserId(userId);
task.setGroupId(groupId);
task.setTaskNum(taskNum);
resWsTask.setTask(task);
log.info("开始发送-接收人:{},消息:{}",userId,msg);
getSessionAndSendMsg(userId, msg, resWsTask, jedis);
}
jedis.close();
}
@OnMessage
public void onMessage(String message,Session session) {
// log.info("收到消息: msg={},sessionid={},sessionSize={},sessionList详情={}" ,message,session.getId(),sessionList.size(),sessionList);
Jedis jedis = RedisAPI.getJedis();
jedis.select(MyWebSocketEnum.WS_SELECT_DATABASE);
String uid= "";
String taskId = "";
if (message.contains("userId") && message.contains("taskId")) {
Map
前端页面:
Title
Welcome
如果是nginx反向代理:
#websocket支持
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
nginx配置后效果图
demo
function getRootPath(){
//获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
var curWwwPath=window.document.location.href;
//获取主机地址之后的目录,如: uimcardprj/share/meun.jsp
var pathName=window.document.location.pathname;
var pos=curWwwPath.indexOf(pathName);
//获取主机地址,如: http://localhost:8083
var localhostPaht=curWwwPath.substring(0,pos);
//获取带"/"的项目名,如:/uimcardprj
var projectName=pathName.substring(0,pathName.substr(1).indexOf('/')+1);
return(localhostPaht+projectName);
}
//------------------websocket 开始-------
var websocket = null;
var url = getRootPath();
var subStrNum = 0;
if (url.indexOf("https://") != -1) {
subStrNum = 8;
}else {
subStrNum = 7;
}
var wsurl = url.substr(subStrNum);
var websocketUrl = null;
//判断当前浏览器是否支持WebSocket
var online_send = setInterval(getWebSocketStatus, 10000);
setTimeout(getWebsocket,500);
setTimeout(getWebSocketStatus,1000);
function getWebsocket() {
websocketUrl = "ws://" + wsurl +"/webSocketService/"+ userId;
if ('WebSocket' in window) {
websocket = new WebSocket(websocketUrl);
}
else {
alert('当前浏览器不支持此访问,请更换谷歌浏览器访问');
}
//连接发生错误的回调方法
websocket.onerror = function () {
te("网络异常,请检查网络...");
};
//连接成功建立的回调方法
websocket.onopen = function () {
// ts("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function (event) {
console.log("收到消息:",event);
console.log("收到消息详情:",event.data);
var taskInfo = JSON.parse(event.data);
var methodType = taskInfo.methodType;
if (methodType == 1) {
return;
}
var taskMsg = taskInfo.task.msg;
var taskNum = taskInfo.task.taskNum;
var taskId = taskInfo.task.taskId;
//如果是100001或者100002是上传或者下载
if(taskNum == 100001 || taskNum == 100002){
getIsHaveNewEvidence(taskId,taskNum,taskMsg);
}
}
//连接关闭的回调方法
websocket.onclose = function () {
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function () {
websocket.close();
}
}
function getWebSocketStatus() {
if (websocket.readyState != WebSocket.OPEN && websocket.readyState != WebSocket.CONNECTING) {
console.log("不满足条件");
websocket = new WebSocket(websocketUrl);
}else {
console.log("满足条件,发送消息");
sendWebsocketMsg(userId,"")
}
}
/**
* 发送websocket信息
*/
function sendWebsocketMsg(userId,taskId){
var obj = new Object();
obj.userId=userId;
obj.taskId=taskId;
if (websocket.readyState == WebSocket.OPEN) {
websocket.send(JSON.stringify(obj));
}else if (websocket.readyState == WebSocket.CONNECTING) {
setTimeout(sendWebsocketMsg(userId,taskId),3000)
}
}