WebSocket消息推送和聊天功能实现

WebSocket消息推送

    • SpringBoot集成WebSocket实现消息推送和聊天Demo
      • gradle引入依赖
      • 测试用的Controller
      • 两个测试页面
      • WebSocket的Endpoint配置类
      • 业务逻辑类

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。现在,很多网站为了实现推送技术,所用的技术都是 Ajax 轮询。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发出HTTP请求,然后由服务器返回最新的数据给客户端的浏览器。这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求,然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

前端JavaScript调用WebSocket基础教程

SpringBoot集成WebSocket实现消息推送和聊天Demo

效果图
WebSocket消息推送和聊天功能实现_第1张图片
为了体现WebSocket的特性我尽量把代码写的简短。除第一个Action用作发布公告其它开一个游览器窗口会自动分配一个用户名。
开窗步骤
localhost:8080/ 发布公告页
localhost:8080/firstPage 用户aa
localhost:8080/firstPage 用户bb
localhost:8080/firstPage 用户cc
localhost:8080/firstPage 用户dd

在页面发送消息时加上 用户名 如:"aa你好吗"

代码结构


一个Controller发布两个Action:发布公告、聊天页
一个WebSocket配置类:发布WebSocket端点(Endpoint)
一个业务逻辑类:实现推送公告和聊天功能
两个Html5页面


gradle引入依赖

    implementation 'org.springframework.boot:spring-boot-starter-websocket'

测试用的Controller

@Controller
public class TestController {
    @RequestMapping("/")
    public String HomeIndexPage(){
        return "Index";
    }
    @RequestMapping("/firstPage")
    public String HomeIndexPage1(){
        return "First";
    }

    @RequestMapping("/publishanews")
    public String publishnewsproc(){
        WebSocketTest webSocketTest = new WebSocketTest();
        webSocketTest.sendMessageForAllClient("这是一条公告!");
        return "Index";
    }
}

两个测试页面




    
    发布公告页
    
    
    




Good Evening

发布公告



    
    聊天室


    

WebSocket的Endpoint配置类

这点和WebServices一样需要播出个端点出去。

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

业务逻辑类

@Service
@ServerEndpoint("/websocket")
public class WebSocketTest {
    private static Vector sessions = new Vector<>();
    private static TreeMap sessionTreeMap = new TreeMap<>();
    private static int loginNumber = 0;
    private Session session ;
    @OnOpen
    public void onopenproc(Session session) throws IOException {
        System.out.println("hava a client connected");
        this.session = session;
        sessions.add(session);
        if(loginNumber == 0)
            loginNumber++;
        else if(loginNumber == 1) {
            sessionTreeMap.put("aa", session);
            loginNumber++;
            sendMessageToClient("我是用户 aa " , session);
        }
        else if(loginNumber == 2) {
            sessionTreeMap.put("bb", session);
            loginNumber++;
            sendMessageToClient("我是用户 bb " , session);
        }
           else if(loginNumber == 3) {
                sessionTreeMap.put("cc", session);
                loginNumber++;
            sendMessageToClient("我是用户 cc " , session);
        }
        else if(loginNumber == 4) {
            sessionTreeMap.put("dd", session);
            loginNumber++;
            sendMessageToClient("我是用户 dd " , session);
        }
    }
    @OnClose
    public void oncloseproc(){
        System.out.println("had a client is disconneted");
    }
    @OnMessage
    public void onmessageproc(String message , Session session) throws IOException {
        if(message!=null) {
            StringBuffer stringBuffer = new StringBuffer();
            sessionTreeMap.forEach((k,v)->{
                if(v.equals(session)){
                    stringBuffer.append(k);
                }
            });

            switch (message.substring(0,2)){
                case "aa" :{
                    sendMessageToClient("From : "+stringBuffer.toString() + " : " + message , sessionTreeMap.get("aa"));
                }break;
                case "bb":{
                    sendMessageToClient("From : "+stringBuffer.toString() + " : " + message , sessionTreeMap.get("bb"));
                }break;
                case "cc":{
                    sendMessageToClient("From : "+stringBuffer.toString() + " : " + message , sessionTreeMap.get("cc"));
                }break;
                case "dd":{
                    sendMessageToClient("From : "+stringBuffer.toString() + " : " + message , sessionTreeMap.get("dd"));
                }break;
            }
            System.out.println(message);
        }
    }

    public void sendMessage(String msg) throws IOException {
        if(this.session!=null)
        this.session.getBasicRemote().sendText("hello everyone!");
        this.session.getBasicRemote().sendText(msg);
    }

    public void sendMessageForAllClient(String msg){
        if(!sessions.isEmpty()){
            sessions.forEach(i->{
                try {
                    if(i.isOpen()) {
                        i.getBasicRemote().sendText(msg+" : "+new Date().toString());
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    public void sendMessageToClient(String msg , Session session) throws IOException {
        if(session.isOpen())
        session.getBasicRemote().sendText(msg);
    }
}

附上项目代码

你可能感兴趣的:(WebSocket消息推送和聊天功能实现)