Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 3868|回复: 0

使用websocket来监控是否异常退出或异常关闭登陆窗口

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-21 15:53:35 | 显示全部楼层 |阅读模式

    知识点websocket获取本机IP&websocket前后端消息推送

    解决的实际问题

    前端用户登陆时同一个账号密码只允许在一个IP上登陆;

    同一个IP只允许登陆一个账户密码。

    主要实现思路:

    1.前端websocket 推送消息,创建一个new websocket,将前端的部分参数传给后台

    sendMsg()  //发送数据

    2.前后端建立连接触发,客户端可以通过这个URL来连接到WebSocket服务器端,当连接成功时则调用其自身的onOpen方法

    后端增加session参数,通过它来给客户端发送数据。

    3.当出现异常或者错误时候前后端都有对应的错误异常处理机制

    后端onError()处理:error.printStackTrace();

    前端onerror处理:websocket.close();

    4.监听窗口关闭事件

    当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。

    window.onbeforeunload = function () {
      websocket.close();
    }

    相关代码实现

    前端js

    // websocket 推送消息

    localIP通过调用接口查询,后面给出,这个是本机IP
    sendWebSocketMsg();

    function sendWebSocketMsg(){
    //判断当前浏览器是否支持WebSocket
    // var test = window.location.host;
    var tstr = userName +","+localIP
    if ('WebSocket' in window) {
    //此处参数只允许字符串,不支持json
    websocket = new WebSocket(getRootPath().replace("http","ws")+"/websocket/"+tstr);
    }
    //连接发生错误的回调方法
    websocket.onerror = function () {
    websocket.close();
    };

    //连接成功建立的回调方法
    websocket.onopen = function () {
    /*
    setInterval(function(){
    websocket.send(userName);
    }, 10000);
    */
    }
    //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
    window.onbeforeunload = function () {
    websocket.close();
    }
    //接收到消息的回调方法
    websocket.onmessage = function (event) {
    }

    //连接关闭的回调方法
    websocket.onclose = function () {
    websocket.close();
    }
    }

     

    java实现

    @ServerEndpoint("/websocket/{tstr}")
    public class WebSocketForJSP {
    //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
    private static int onlineCount = 0;

    //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
    public static CopyOnWriteArraySet<WebSocketForJSP> webSocketSet = new CopyOnWriteArraySet<WebSocketForJSP>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;
    // 登录用户名
    public String userName;
    //所属IP
    public String ip;


    /**
    * 连接建立成功调用的方法
    * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
    */
    @OnOpen
    public void onOpen(@PathParam("tstr") String tstr, Session session){
    String[] str = tstr.split(",");

    this.userName = str[0];
    this.ip = str[1];
    this.session = session;
    webSocketSet.add(this); //加入set中
    addOnlineCount(); //在线数加1
    System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    }
    // public void onOpen(@PathParam("name") String name, Session session){
    // this.userName = name;
    // this.session = session;
    // webSocketSet.add(this); //加入set中
    // addOnlineCount(); //在线数加1
    // System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
    // }

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

    /**
    * 收到客户端消息后调用的方法
    * @param message 客户端发送过来的消息
    * @param session 可选的参数
    */
    @OnMessage
    public void onMessage(String message, Session session) {
    System.out.println("来自客户端的消息:" + message);
    /*
    userName = message;
    for(WebSocketForJSP item: webSocketSet){
    try {
    item.sendMessage(message);
    } catch (IOException e) {
    e.printStackTrace();
    continue;
    }
    }
    */
    }

    /**
    * 发生错误时调用
    * @param session
    * @param error
    */
    @OnError
    public void onError(Session session, Throwable error){
    System.out.println("发生错误");
    error.printStackTrace();
    }

    /**
    * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
    * @param message
    * @throws IOException
    */
    public void sendMessage(String message) throws IOException{
    this.session.getBasicRemote().sendText(message);
    //this.session.getAsyncRemote().sendText(message);
    }

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

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

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

    支持javax的包需要引入

    .xml

    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>7.0</version>
      <scope>provided</scope>
    </dependency>

    有关获取本机IP

    需要调用某个接口,将request带过去 调用下面的方法即可实现,这个接口随便自己些,只要能ajax调用到就可以

     

    @RequestMapping(value="getip")
    @ResponseBody
    public String getip(HttpServletRequest request){
    User userInfo = (User) request.getSession().getAttribute("user");
    String ip = userInfo.getIpaddr();
    return ip;
    }

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-5 02:37 , Processed in 0.063342 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表