websocket的使用

依赖包    

 <!--实时通信的依赖包-->
      <dependency>
        <groupId>javax.websocket</groupId>
        <artifactId>javax.websocket-api</artifactId>
        <version>1.1</version>
        <scope>provided</scope>
      </dependency>

开发一个服务端程序用来广播消息

  实体类

package com.seecen.ws;

/**
 * Author: CalcYu
 * Date: 2019/8/12
 */
public class Message {
    //-1: 群聊 2:私聊 0:系统 999:特殊操作
    private int type;

    //内容
    private String content;

    //私聊接收者
    private Integer toUser;


    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Integer getToUser() {
        return toUser;
    }

    public void setToUser(Integer toUser) {
        this.toUser = toUser;
    }
}

  特效实体类

package com.seecen.ws;

/**
 * Author: CalcYu
 * Date: 2019/8/13
 */
public class Msg {
    /**
     * 1:系统上/下线消息
     * 4:用户文本消息
     * 5:收到用户抖动消息
     * 6:收到用户撤回消息
     */
    private int type;
    private String username;
    private int messageId;
    private String content;

    public Msg() {
    }

    public Msg(int type, String username, int messageId, String content) {
        this.type = type;
        this.username = username;
        this.messageId = messageId;
        this.content = content;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getMessageId() {
        return messageId;
    }

    public void setMessageId(int messageId) {
        this.messageId = messageId;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}

给websocket服务定义一个连接的地址

package com.seecen.ws;

import com.alibaba.fastjson.JSON;
import com.seecen.controller.LoginController;
import com.seecen.entity.User;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Author: CalcYu
 * Date: 2019/8/9
 * 1.客户端建立连接
 * 2.客户端断开连接
 * 3.客户端发送消息
 */
//给websocket服务定义一个连接的地址
//ws:localhost:8080/my_chat
@ServerEndpoint(value = "/my_chat", configurator = GetHttpSession.class)
public class ChatServer {

    //声明一个集合来保存客户断程序,建立连接或断开连接都是并发操作
    private static CopyOnWriteArraySet<ChatServer> clients = new CopyOnWriteArraySet<>();

    private Session session;
    //每个ChatServer绑定一个User对象
    private User user;

    /**
     * 当建立连接执行
     * 创建连接时会创建一个session对象
     * 每个客户端会创建 一个ChatServer对象 每个对象有一个session
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        this.session = session;
        clients.add(this);
        //从配置文件中获取httpSession对象及User对象
        HttpSession httpSession = (HttpSession)
                config.getUserProperties().get(HttpSession.class.getName());
        //获取httpSession中的User对象
        User user = (User) httpSession.getAttribute(LoginController.USER_INFO);
        this.user = user;
        System.out.println("有新的连接加入,当前在线人数为:" + clients.size());
    }

    /**
     * 当断开连接执行
     */
    @OnClose
    public void onClose() {
        clients.remove(this);
        System.out.println("有一个用户退出,当前在线人数为:" + clients.size());
    }

    /**
     * 当发送消息执行
     *
     * @param msg
     */
    @OnMessage
    public void onMessage(String msg) {
        //传递比较丰富的消息可以采用json
        //如果给客户端主动发送消息
        //广播
        //把字符串还原成对象
        Message message = JSON.parseObject(msg, Message.class);
        //当类型为-1时 群聊,把消息content广播给所有在线用户
        if (message.getType() == -1) {
            for (ChatServer chat : clients) {
                try {
                    //<p style="color: green">群聊消息</p>
                    String html = "<p style='color: green'>%s</p>";
                    chat.getSession().getBasicRemote().sendText(String.format(html,message.getContent()));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else if (message.getType() == 2) {
            //私聊
//            遍历集合找到对应用户进行推送(问题:并不知道哪个ChatServer对象是哪个用户)
            for (ChatServer c : clients) {
                if (c.getUser().getUserId().intValue() == message.getToUser()) {
                    //  张三对李四说:晚上吃什么?
                    //<p style="color: red">私聊消息</p>
                    String html = "<p style='color: red'>%s</p>";
                    String content = this.user.getUserName() + "对" + c.getUser().getUserName() + ":" + message.getContent();
                    try {
                        c.getSession().getBasicRemote().sendText(String.format(html, content));
                        //给自己发送消息
                        this.getSession().getBasicRemote().sendText(String.format(html, content));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }

    }

    //当websocket出错会执行
    @OnError
    public void onError(Throwable e){
        e.printStackTrace();
    }

    public User getUser() {
        return user;
    }

    //只能读取不能修改
    public Session getSession() {
        return session;
    }
}

开发一个客户端程序用来发送和接收消息

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .main {
            width: 350px;
            margin: 0 auto;
        }

        .main #msgBox {
            width: 100%;
            height: 300px;
        }
    </style>
</head>
<body>
<div class="main">
    <div id="msgBox" ></div>
    <select name="" id="user">
        <option value="-1">所有人</option>
        <option value="3">张三</option>
        <option value="6">李四</option>
    </select>
    <input type="text" id="inputTxt">
    <input type="button" id="sendBtn" value="发送">
</div>
<script src="/js/jquery.min.js"></script>
<script>
    //字面量的方式传递一个对象
    var obj = {userName: "1111", userPsw: "123"};
    var obj2 = new Object();
    obj2.userName = "123123";

    //把js对象转换成字符串
    var jsonStr = JSON.stringify(obj);
    //把字符串转换成对象
    var jsObj = JSON.parse(jsonStr);
    //同时打印多个变量值
    console.log(obj, obj2, jsonStr, jsObj);


    //当页面加载完成连接服务器程序
    var url = "ws://localhost:8866/my_chat";
    var ws = new WebSocket(url);
    if (ws) {
        //采用监听的方式来绑定回调函数
        ws.onopen = function (event) {
            console.log("连接服务器成功");
            $("#msgBox").append("连接服务器成功\n");
        }
        ws.onclose = function (event) {
            $("#msgBox").append("服务器连接中断\n");
        }
        ws.onmessage = function (event) {
            $("#msgBox").append(event.data + "\n");
        }
        //主动给服务器发送消息
        $("#sendBtn").click(function () {
            var msg = $("#inputTxt").val();
            if (msg) {
                var msgType = $("#user").val();
                if (msgType == -1) {
                    //发送给所有人
                    var msgObj = {type: -1, content: msg};
                    ws.send(JSON.stringify(msgObj));
                } else {
                    //私聊
                    var msgObj = {type: 2, content: msg, toUser: msgType};
                    ws.send(JSON.stringify(msgObj))
                }

            }
        })
    } else {
        alert("浏览器版本过低,不支持websocket协议");
    }
</script>
</body>
</html>

websocket使用细节

  1. 如何通过json传递信息
  2. 如何把json字符串还原回一个对象  

      依赖包

        fastjson (阿里巴巴开源的) 

 <!--json转换依赖包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.31</version>
        </dependency> 

    JSON api

      toJSONString 方法

      parseObject 方法

      parseArray 方法

    html里面转换

      js中进行互转  

JSON.stringify(obj);
JSON.parse(jsonStr);

    WebSocket中如何获取HttpSession对象中的User

      增加终端配置文件

package com.seecen.ws;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;

/**
 * Author: CalcYu
 * Date: 2019/8/12
 * 自定义终端配置文件获取httpSession中的对象
 */
public class GetHttpSession extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        //获取httpSession对象,保存至终端配置文件的用户属性中
        HttpSession session = (HttpSession) request.getHttpSession();
        if (session != null) {
            sec.getUserProperties().put(HttpSession.class.getName(), session);
        }
    }
}

   web.xml中可以设置websocket文本缓存大小

 <!--设置websocket文本缓存大小-->
    <context-param>
        <param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
        <param-value>5242800</param-value>
    </context-param>

 

posted @ 2019-09-12 09:19  changlinlo  阅读(531)  评论(0编辑  收藏  举报