使用RabbitMQ、WebSocker、stopm简单实现聊天室功能

先看看简陋的聊天室

一起来聊聊
实现此功能需要使用到技术有:SpringBoot、RabbitMQ、WebSocker、stopm、sockjs、docker、bootstrap、ajax。

首先在Docker中拉取RabbitMQ镜像,先运行RabbitMQ镜像,进入RabbitMQ容器中,开启RabbitMQ插件,让其支持stopm协议。

rabbitmq-plugins enable rabbitmq_web_stomp rabbitmq_stomp rabbitmq_web_stomp_examples

这里有个跨域问题,如果不设置的话,消息无法跨域,就无法在不同域名下进行消息传送,自己玩的时候建议全部允许跨域,在项目中可以指定域名允许跨域消息。

在rabbitmq.conf中加上management.cors.allow_origins.1 = * 。星表示全部允许跨域,该配置文件在容器/etc/rabbitmq/目录下,在容器中不允许修改文件内容,这里还需要进行配置挂载,在宿主机目录下创建/usr/rabbitmq/conf目录,将容器中的配置文件和插件配置都拷贝到此目录下:

插件配置名:enabled_plugins
插件内容:

[rabbitmq_management,rabbitmq_stomp,rabbitmq_web_stomp,rabbitmq_web_stomp_examples].

配置文件名:rabbitmq.conf
配置内容:

loopback_users.guest = false
listeners.tcp.default = 5672
management.tcp.port = 15672
management.cors.allow_origins.1 = *

删除之前运行的容器,再次启动镜像,需要在启动时挂载一些参数

docker run -d -p 15672:15672 5672:5672 15674:15674 15670:15670 -v /usr/rabbitmq/conf:/etc/rabbitmq --name myrabbitmq rabbitmq:3.7.26

访问15670端口,看到以下内容表示你设置并启动成功了!
在这里插入图片描述

创建一个SpringBoot项目(发送方),依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

配置信息:

# 应用服务 WEB 访问端口
server.port=8081
server.servlet.context-path=/
# 连接RabbitMQ配置
spring.rabbitmq.host=192.168.2.113
spring.rabbitmq.port=5672
spring.rabbitmq.username=root
spring.rabbitmq.password=123456

前端页面:

扫描二维码关注公众号,回复: 15057979 查看本文章
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>带码人聊天室1</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script language="javascript" type="text/javascript" th:src="@{/js/jquery-3.5.0.js}"></script>
    <script th:src="@{/js/jquery.js}"></script>
    <script type="text/javascript">
        $(function () {
    
    
            $("#mess").focus(function () {
    
    
                $("#tip").text("")
            });
            $("#but").click(function () {
    
    
                var message = $("#mess").val();

                if (message==""){
    
    
                    alert("please input!")
                    return;
                }
                $.ajax({
    
    
                    url:basepath+"/send",
                    data:{
    
    
                        message:message
                    },
                    success:function (data) {
    
    
                        $("#tip").text(data)
                        $("#mess").val("");
                        let date = new Date();
                        let dateHours = date.getHours();               //获取小时
                        let dateMinutes = date.getMinutes();           //获取分钟
                        let dateSeconds = date.getSeconds();           //获取秒
                        $("#message").append("myself >"+dateHours+"时"+dateMinutes+"分"+dateSeconds+"秒:",message + "<br/>");
                    }
                })
            });
        })
        //按enter键触发送按钮
        $(window).keydown(function (e) {
    
    
            if (e.keyCode == 13) {
    
    
                $("#but").click()
            }
        });

<div th:include="commons/common :: html"></div>

<div class="row">
    <div class="col-md-2 col-md-offset-5">
        <h1>welcome (´▽`ʃ♡ƪ)</h1>
        <input  type="text" id="mess" placeholder="send you want"> <button class="btn btn-success" type="button" id="but">send</button>
        <div><span id="tip" style="color: green"></span></div>
        <hr>
      </div>
    <div id="log"></div>
</div>

</body>
</html>

发送消息服务类:

//加入spring容器
@Component
public class SendService {
    
    

    @Autowired
    AmqpTemplate amqpTemplate;

    public void send(String exchange,String routingKey,String message){
    
    
        amqpTemplate.convertAndSend(exchange,routingKey,message);
        System.out.println("消息发送成功");
    }

}

控制层:

@Controller
public class SendController {
    
    

    @Autowired
    ApplicationContext applicationContext;

    @RequestMapping("/send")
    @ResponseBody
    public Object index(String message){
    
    
        SendService sendService = (SendService) applicationContext.getBean("sendService");
        sendService.send("myEx-direct","chen",message);
        return "发送成功";
    }
}

这里主要是在前端获取发送的信息,通过异步请求,将信息参数传递给后端控制层,控制层调用发送消息的服务,将信息发送到消息中间件的队列中

再次创建一个SpringBoot项目(接收方):
前端页面:
这里必须引入sockjs.js、stomp.js

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>测试接收</title>
    <script th:src="@{/js/jquery.js}"></script>
    <script th:src="@{/js/sockjs.js}"></script>
    <script th:src="@{/js/stomp.js}"></script>
    <script>
        //初始化 ws 对象,使用的是rabbitmq_stomp的端口【15674】
        var ws = new WebSocket('ws://192.168.2.113:15674/ws');
        // 获得Stomp client对象
        var client = Stomp.over(ws);
        //发送频率
        client.heartbeat.outgoing = 0;
        //接收频率
        client.heartbeat.incoming = 0;
        //关闭控制台调试数据:client.debug = null
        client.debug = function (str) {
    
    
            $("#debug").append(str + "<br/>");
        };
        // 定义连接成功回调函数
        var on_connect = function (x) {
    
    
            //接收myqueue队列的数据
            //注意 /queue/是必须的,后面填写你自己创建的队列名称
            client.subscribe("/queue/myqueue", function (data) {
    
    
                var msg = data.body;
                $("#log").text("收到数据");
                console.log(data);
                $("#message").append(msg + "<br/>");
                //如果后面带了参数 ack  就是指定要手动确认消息,没带就是自动确认
                data.ack();
            }, {
    
    ack: 'client'});
        };
        // 定义错误时回调函数
        var on_error = function () {
    
    
            $("#log").val("error")
        };
        // 连接RabbitMQ
        client.connect('root', '123456', on_connect, on_error, '/');
    </script>
</head>
<body>
<h1 th:text="ok"></h1>
<h1>debug</h1>
<div id="debug"></div>
<hr>
<h1>data</h1>
<div id="message"></div>
<hr>
<h1>接收消息情况</h1>
<div id="log"></div>
</body>
</html>

登录RabbitMQ客户端,通过(RoutingKey)路由键将交换机与队列绑定,启动两个项目,发送方发送信息,接收方就能实时接收信息了。

总结:
这只是实现了消息的单发面发送,要想实现开始的聊天室功能(就是将两方的代码互相拷贝一下),需要再创建一个队列,让发送方监听接收方队列的消息,接收方也监听着发送方队列的信息,这样就实现了一个简单的聊天室的功能。

猜你喜欢

转载自blog.csdn.net/m0_46803792/article/details/107609747