WebSocket实现服务器主动推送消息给浏览器客户端

java端代码

package org.jeecg.modules.cases.controller;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArraySet;

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

import lombok.extern.log4j.Log4j2;
import org.jeecg.config.SpringUtil;
import org.jeecg.modules.system.entity.SysUserDepart;
import org.jeecg.modules.system.mapper.SysUserDepartMapper;
import org.jeecg.modules.system.mapper.SysUserRoleMapper;
import org.springframework.stereotype.Component;

@Log4j2
@ServerEndpoint("/websocket/{uid}")
@Component
public class WebSocketServer {
    //有时候会因为初始化类属性时容器中还未有相应的been造成创建WebSocketServer been失败,可以考虑将下边的两个属性在要使用的地方获取使用
    private static SysUserDepartMapper sysUserDepartMapper= SpringUtil.getBean(SysUserDepartMapper.class);
    private static SysUserRoleMapper sysUserRoleMapper= SpringUtil.getBean(SysUserRoleMapper.class);
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;
    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
    //在真正的使用中这个set的大小回应为非正规的退出(没调用close方法就关闭页面了),导致数量只增不减,后期需要一个客户端定期的一个心跳机制来控制删除一些已死的连接
    private static CopyOnWriteArraySet webSocketSet = new CopyOnWriteArraySet();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //用户id
    private String uid="";
    //用户数所属部门
    private String depid="";
    //用户所属部门
    private String roleid="";
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session,@PathParam("uid") String uid) {
        List deps = sysUserDepartMapper.getUserDepartByUid(uid);//根据用户id获取部门
        List roles = sysUserRoleMapper.getRoleIdByUserId(uid);//根据用户id获取角色
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        log.info("有新窗口开始监听:"+uid+",当前在线人数为" + getOnlineCount()+"|"+webSocketSet.size());
        this.uid=uid;
        if (deps!=null&&deps.size()>0) {
            this.depid = deps.get(0).getDepId();
        }
        if (roles!=null&&roles.size()>0) {
            this.roleid = roles.get(0);
        }
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            log.error("websocket IO异常");
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session) {
       log.info("收到来自窗口"+uid+"的信息:"+message);
        //群发消息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage(message);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

   /**
    * 
    * @param session
    * @param error
    */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
   /**
    * 实现服务器主动推送
    */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 发送消息到用户
     * */
    public static void sendInfoToUser(String message,@PathParam("uid") String uid) throws IOException {
       log.info("推送消息到窗口"+uid+",推送内容:"+message);
        for (WebSocketServer item : webSocketSet) {
            try {
               //这里可以设定只推送给这个sid的,为null则全部推送
               if(uid==null) {
                  item.sendMessage(message);
               }else if(item.uid.equals(uid)){
                  item.sendMessage(message);
               }
            } catch (IOException e) {
                continue;
            }
        }
        log.info("推送完毕");
    }
    /**
     * 发送消息到部门
     * */
    public static void sendInfoToDep(String message,@PathParam("depid") String depid) throws IOException {
       log.info("推送消息到窗口"+depid+",推送内容:"+message);
        for (WebSocketServer item : webSocketSet) {
            try {
               //这里可以设定只推送给这个sid的,为null则全部推送
               if(depid==null) {
                  item.sendMessage(message);
               }else if(item.depid.equals(depid)){
                  item.sendMessage(message);
               }
            } catch (IOException e) {
                continue;
            }
        }
    }
    /**
     * 发送消息到角色
     * */
    public static void sendInfoToRole(String message,@PathParam("roleid") String roleid) throws IOException {
       log.info("推送消息到窗口"+roleid+",推送内容:"+message);
        for (WebSocketServer item : webSocketSet) {
            try {
               //这里可以设定只推送给这个sid的,为null则全部推送
               if(roleid==null) {
                  item.sendMessage(message);
               }else if(item.roleid.equals(roleid)){
                  item.sendMessage(message);
               }
            } catch (IOException e) {
                continue;
            }
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}

模仿消息推送接口接口java代码(CaseMsgVO.java类自己建完成重写tostring即可) :

package org.jeecg.modules.cases.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.cases.entity.AppHistoryData;
import org.jeecg.modules.cases.mapper.SysFilesMapper;
import org.jeecg.modules.cases.service.IAppMeService;
import org.jeecg.modules.cases.vo.AppMeVO;
import org.jeecg.modules.cases.vo.AppVersionVO;
import org.jeecg.modules.system.vo.CaseMsgVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.List;

@Slf4j
@Api(tags="WebSocaket推送消息")
@RestController
@RequestMapping("/dowebsocaket")
public class WebSocaketController {

    @ApiOperation(value="推送消息", notes="")
    @GetMapping(value = "/pushmsg")
    public void getNewAppVersion(String uid) throws IOException {
        CaseMsgVO tmpm = new CaseMsgVO();
        tmpm.setAnntId("ausdtuiqweuyuds");
        tmpm.setTitle("督办信息");
        tmpm.setMsgContent("你有一条交办单被督办。。。。。。。。。。。");
        WebSocketServer.sendInfoToUser(tmpm.toString(),uid);//真正的业务中哪里需要发送消息就在哪里调用即可
    }
}

JavaScript代码:

  

 

启动java项目后将上边的JavaScript代码写入一个.html后缀文件用浏览器打开后如图:

WebSocket实现服务器主动推送消息给浏览器客户端_第1张图片

 

 

swagger中模仿消息发送:

WebSocket实现服务器主动推送消息给浏览器客户端_第2张图片

调用上边的接口后:

WebSocket实现服务器主动推送消息给浏览器客户端_第3张图片

你可能感兴趣的:(WebSocket实现服务器主动推送消息给浏览器客户端)