太赞了,竟然用SpringBoot打造一款网页版的IM,进行聊天...

简介: 太赞了,竟然用SpringBoot打造一款网页版的IM,进行聊天...

目录


  • 传统 Tomcat 开发 WebSocket 回顾
  • SpringBoot 整合 Tomcat  WebSocket
  • websocket 通信测试


传统 Tomcat 开发 WebSocket 回顾


WebSocket 的出现是基于 Web 应用的实时性需要而产生的,在淘宝、京东等网页客服、网页卖家聊天等需求上应用广泛。对于前端网页可以使用 H5 开发 WebSocket 客户端,也可以使用 SockJS 库开发 WebSocket 客户端。


对于Java 开发者而言,后台 WebSocket 服务端开发通常有以下常用的选择:

  • Tomcat7 以后开始支持 websocket 协议
  • Spring4 以后开始支持 WebSocket
  • Netty3 以后支持开发 WebSocket


Tomcat8 如下所示,自身已经支持 WebSocket 服务端开发,它的 lib 目录下有自己实现 WebSocket 协议的开发包,如果是传统的 Java Web 项目,则只需要将 tomcat-websocket.jar、websocket-api.jar 导入应用中即可进行代码开发。

image.gif

Tomcat 自身也提供了 WebSocket 开发的示例,在 webapps/exampls下,一共提供了 4 个示例,可以启动 Tomcat 进行访问测试以及学习:image.gifimage.gif

对于传统 Java Web 导包式应用开发,这里不再过多进行说明,它的基本流程是:

1)新建 Java Web 应用后,导入 Tomcat 服务器 lib 目录下的 websocket-api.jar 、tomcat-websocket.jar开发包,前者是浏览器 webSocket 规范的接口,后者是 Tomcat 对它的实现

2)创建后台 webSocket 服务端类,标识 @ServerEndpoint( javax.websocket.server.ServerEndpoint)注解,表示当前类是 webSocket 服务终端,同时在里面实现客户端连接建立、发送消息、接收消息等通信业务。

3)自己实现 javax.websocket.server.ServerApplicationConfig 接口,扫描整个应用所有的 @ServerEndpoint 服务终端


SpringBoot 整合 Tomcat  WebSocket


本文的重点是 SpringBoot 项目如何使用 Tomcat 的 webSocket 服务端开发;本文环境:springboot 2.1.0 ,使用内置的 Tomcat 服务器。

image.png

Spring boot 创建的 web 应用,web 启动模块已经依赖了 tomcat-websocket 模块,所以不需要再重复导入,但是必须导入 Spring boot 的 websocket 启动模块 spring-boot-starter-websocket。image.png


<!-- Spring boot WebSocket-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>


@ServerEndpoint 创建 websocket 服务终端


1、创建后台 webSocket 服务端类,标识 @ServerEndpoint( javax.websocket.server.ServerEndpoint)注解,表示当前类是 webSocket 服务终端,同时在里面实现客户端连接建立、发送消息、接收消息等通信业务。


2、这与传统导包式开发 Tomcat WebSocket 服务端是一样的,区别就是:传统方式 @ServerEndpoint 类上不需要加 @Component 交由 Spring 管理,而现在需要加上 @Component 将此组件交由 spring 管理。

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
 * Created by Administrator on 2018/11/28 0028.
 * @ServerEndpoint :标识此类为 Tomcat 的 websocket 服务终端,/websocket/yy.action 是客户端连接请求的路径
 * @Component :将本类交由 spring IOC 容器管理
 */
@ServerEndpoint(value = "/websocket/yy.action")
@Component
public class ServerEnpoint {
    private static Logger logger = LoggerFactory.getLogger(ServerEnpoint.class);
    /**
     * 用 Set 来 存储 客户端 连接
     */
    private static Set<Session> sessionSet = new HashSet<>();
    /**
     * 连接成功后自动触发
     *
     * @param session
     */
    @OnOpen
    public void afterConnectionEstablished(Session session) {
        /**
         * session 表示一个连接会话,整个连接会话过程中它都是固定的,每个不同的连接 session 不同
         * String queryString = session.getQueryString();//获取请求地址中的查询字符串
         * Map<String, List<String>> parameterMap = session.getRequestParameterMap();//获取请求地址中参数
         * Map<String, String> stringMap = session.getPathParameters();
         * URI uri = session.getRequestURI();
         */
        sessionSet.add(session);
        logger.info("新客户端加入,session id=" + session.getId() + ",当前客户端格个数为:" + sessionSet.size());
        /**
         * session.getBasicRemote().sendText(textMessage);同步发送
         * session.getAsyncRemote().sendText(textMessage);异步发送
         */
        session.getAsyncRemote().sendText("我是服务器,你连接成功!");
    }
    /**
     * 连接断开后自动触发,连接断开后,应该清楚掉 session 集合中的值
     *
     * @param session
     */
    @OnClose
    public void afterConnectionClosed(Session session) {
        sessionSet.remove(session);
        logger.info("客户端断开,session id=" + session.getId() + ",当前客户端格个数为:" + sessionSet.size());
    }
    /**
     * 收到客户端消息后自动触发
     *
     * @param session
     * @param textMessage :客户端传来的文本消息
     */
    @OnMessage
    public void handleMessage(Session session, String textMessage) {
        try {
            logger.info("接收到客户端信息,session id=" + session.getId() + ":" + textMessage);
            /**
             * 原样回复文本消息
             * getBasicRemote:同步发送
             * session.getAsyncRemote().sendText(textMessage);异步发送
             * */
            session.getBasicRemote().sendText(textMessage);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * 消息传输错误后
     *
     * @param session
     * @param throwable
     */
    @OnError
    public void handleTransportError(Session session, Throwable throwable) {
        System.out.println("shake client And server handleTransportError,session.getId()=" + session.getId() + " -- " + throwable.getMessage());
        logger.error("与客户端 session id=" + session.getId() + " 通信错误...");
    }
}


注入 ServerEndpointExporter


1、注入 org.springframework.web.socket.server.standard.ServerEndpointExporter,这个 bean 会自动注册使用了@ServerEndpoint 注解声明的 Websocket endpoint 。


2、如果使用独立的 servlet 容器,而不是使用 spring boot 的内置容器,就不要注入ServerEndpointExporter,因为它将由 Tomcat 容器自己提供和管理。


3、因为传统导包式 Tomcat websocket 开发时,是需要实现 javax.websocket.server.ServerApplicationConfig 接口的,然后由它去扫描整个应用中的 @ServerEndpoint,而现在这一步就由 springboot 的 ServerEndpointExporter 取代了。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
 * Created by Administrator on 2018/11/28 0028.
 */
@Configuration
public class WebSocketConfig {
    /**
     * 创建 ServerEndpointExporter 组件,交由 spring IOC 容器管理,
     * 它会自动扫描注册应用中所有的 @ServerEndpoint
     *
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}


前端 H5 webSocket 客户端


为了方便,直接使用 H5 的 webSocket 方式,页面的 html 与 css 样式就不做提供了,直接提供客户端 webSocket 的 js 代码。

/**
 * web socket 绑定
 */
var ws = null;
function webSocketBind() {
    /**主流浏览器现在都支持 H5 d的 webSocket 通信,但建议还是要判断*/
    if ("WebSocket" in window) {
        /**创建 web socket 实例
         * 如果连接失败,浏览器控制台报错,连接失败
         * 前缀 ws:// 必须正确,yyServer 是应用名称,websocket/yy.action 是后台访问路径
         * 192.168.1.20:websocket 服务器地址
         * */
        ws = new WebSocket("ws://192.168.1.20/yyServer/websocket/yy.action");
        /**onopen:服务器连接成功后,自动触发*/
        ws.onopen = function () {
            /** Web Socket 已连接上,使用 send() 方法发送数据*/
                //ws.send("connect success...");
            console.log("服务器连接成功,并发送数据到后台...");
        };
        /**服务器发送数据后,自动触发此方法,客户端进行获取数据,使用 evt.data 获取数据*/
        ws.onmessage = function (evt) {
            var received_msg = evt.data;
            console.log("接收到服务器数据:" + received_msg);
            showClientMessage(received_msg);
        };
        /**客户端与服务器数据传输错误时触发*/
        ws.onerror = function (evt) {
            console.log("客户端 与 服务器 数据传输错误...");
        };
        /**web Socket 连接关闭时触发*/
        ws.onclose = function () {
            console.log("web scoket 连接关闭...");
        };
    } else {
        alert("您的浏览器不支持 WebSocket!");
    }
}
/**
 * 显示服务器发送的消息
 * @param message
 */
let showServerMessage = function (message) {
    if (message != undefined && message.trim() != "") {
        /**
         * 往服务器发送消息
         */
        ws.send(message.trim());
        /**
         * scrollHeight:div 区域内文档的高度,只能 DOM 操作,JQuery 没有提供相应的方法
         * @type {string}
         */
        let messageShow = "<div class='messageLine server'><div class='messageContent serverCon'>" + message + "</div><span>:我</span>";
        $(".centerTop").append(messageShow + "<br>");
        $(".messageArea").val("");
        let scrollHeight = $(".centerTop")[0].scrollHeight;
        $(".centerTop").scrollTop(scrollHeight - $(".centerTop").height());
    }
};
/**
 * 显示客户端的消息
 * @param message
 */
let showClientMessage = function (message) {
    if (message != undefined && message.trim() != "") {
        /**
         * scrollHeight:div 区域内文档的高度,只能 DOM 操作,JQuery 没有提供相应的方法
         * @type {string}
         */
        let messageShow = "<div class='messageLine client'><span>服务器:</span><div class='messageContent clientCon'>" + message + "</div>";
        $(".centerTop").append(messageShow + "<br>");
        $(".messageArea").val("");
        let scrollHeight = $(".centerTop")[0].scrollHeight;
        $(".centerTop").scrollTop(scrollHeight - $(".centerTop").height());
    }
};
$(function () {
    /**初始化后清空消息发送区域*/
    $(".messageArea").val("");
    /**
     * 为 消息 发送按钮绑定事件
     */
    $(".sendButton").click(function () {
        let message = $(".messageArea").val();
        showServerMessage(message);
    });
    /**
     * 绑定键盘敲击事件 —— 用于按 回车键 发送消息
     */
    $(window).keydown(function (event) {
        if (event.keyCode === 13) {
            let message = $(".messageArea").val();
            showServerMessage(message);
        }
    });
    /**
     * 绑定 webSocket,连接 服务器
     */
    webSocketBind();
});


websocket 通信测试

4.gif

5.gif


作者:蚩尤后裔

来源:https://blog.csdn.net/wangmx1993328/article/details/84582904

目录
相关文章
|
2月前
|
小程序 前端开发 Java
SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
JavaDog Chat v1.0.0 是一款基于 SpringBoot、MybatisPlus 和 uniapp 的简易聊天软件,兼容 H5、小程序和 APP,提供丰富的注释和简洁代码,适合初学者。主要功能包括登录注册、消息发送、好友管理及群组交流。
62 0
SpringBoot+uniapp+uview打造H5+小程序+APP入门学习的聊天小项目
|
5月前
|
Java 网络安全
几个基于springboot在线服务过段时间突然停掉的原因
几个基于springboot在线服务过段时间突然停掉的原因
99 0
|
2月前
|
网络协议 Java 物联网
MQTT(EMQX) - SpringBoot 整合MQTT 连接池 Demo - 附源代码 + 在线客服聊天架构图
MQTT(EMQX) - SpringBoot 整合MQTT 连接池 Demo - 附源代码 + 在线客服聊天架构图
315 2
|
3月前
|
存储 SQL 测试技术
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍+lw)(2)
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍+lw)
108 2
|
3月前
|
JavaScript Java 关系型数据库
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍+lw)(1)
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍+lw)
98 1
|
3月前
|
JavaScript Java 关系型数据库
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍)(1)
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍)
41 0
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍)(1)
|
4月前
|
前端开发 JavaScript 网络协议
Springboot中为什么你能通过一小段代码来访问网页?
Springboot中为什么你能通过一小段代码来访问网页?
44 7
|
4月前
|
缓存 前端开发 UED
Web网页端IM产品RainbowChat-Web的v7.0版已发布
RainbowChat-Web是一套Web网页端IM系统,是RainbowChat的姊妹系统(RainbowChat是一套基于开源IM聊天框架 MobileIMSDK (Github地址) 的产品级移动端IM系统)。
70 1
|
3月前
|
存储 SQL 测试技术
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍)(2)
基于SpringBoot+Vue交通管理在线服务系统的开发(源码+部署说明+演示视频+源码介绍)
34 0
|
3月前
|
小程序
【亲测有效】3步实现 微信小程序内接入小程序客服,网页端客服工具与移动端小程序客服工具使用方法,使用入口,并设置当前客服状态
【亲测有效】3步实现 微信小程序内接入小程序客服,网页端客服工具与移动端小程序客服工具使用方法,使用入口,并设置当前客服状态
161 0

热门文章

最新文章

下一篇
无影云桌面