欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

基于STOMP协议 实现的简单在线聊天 技术点:springboot+websocket+sockjs

程序员文章站 2022-05-21 09:31:07
...

1、websocket 简单了解

WebSocket协议RFC 6455提供了一种标准化方法,可以通过单个TCP连接在客户端和服务器之间建立全双工双向通信通道。它是与HTTP不同的TCP协议,但旨在通过端口80和443在HTTP上工作,并允许重复使用现有的防火墙规则。

WebSocket交互始于一个HTTP请求,该请求使用HTTP Upgrade标头进行升级,或者在这种情况下切换到WebSocket协议。以下示例显示了这种交互:

GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket (1)
Connection: Upgrade  (2)
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080

(1)该Upgrade

(2)使用Upgrade连接

具有WebSocket支持的服务器代替通常的200状态代码,返回类似于以下内容的输出:

HTTP/1.1 101 Switching Protocols 
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp

以上均摘自spring官网,具体的就不介绍了,我把链接放这里,需要了解的自己点开看好了

具体链接:点我去spring官网查看具体的websocket

2、具体实现

主要功能:  1、联系人列表上要有所有上线的人员,并且实现实时更新

                  2、实现一对一的在线实时聊天

先上效果图:

2个浏览器  模拟 唐僧 和悟空 登录

基于STOMP协议 实现的简单在线聊天 技术点:springboot+websocket+sockjs

唐僧找悟空聊天

唐僧发了: 空空,我们去花果山ktv吧

悟空回复:不去,你上次还没有结账呢

基于STOMP协议 实现的简单在线聊天 技术点:springboot+websocket+sockjs

一个简易的实时在线聊天,这是个简单的demo,所以布局和聊天的逻辑还不是很完善。

这个效果实现需要的了解几个知识:

1、前端:ui框架是用的layui  可以自行百度了解一下

                2 个html互相传值的问题,网上大概有3中方法,这里用的是window.open和window.opener之间传值。

2、后端:springboot+websocket  

 先上后端的代码:

pom.xml 

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.demo.chat</groupId>
    <artifactId>chat-chat</artifactId>
    <version>1.0-SNAPSHOT</version>



    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>



        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>


        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.0.2</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>bootstrap</artifactId>
            <version>3.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
</project>

WebSocketConfig类 

用来配置WebSocketConfig相关信息

@Configuration
///注解开启使用STOMP协议来传输基于代理(message broker)的消息,这时控制器支持使用@MessageMapping
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * 配置消息代理
     * @param config
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        //允许订阅的前缀   点对点应配置一个/user消息代理,广播式应配置一个/topic消息代理
        config.enableSimpleBroker("/topic","/user");

        //路由到controller
        config.setApplicationDestinationPrefixes("/app");
    }


    /**
     * //注册STOMP协议的节点(chat),并映射指定的url
     * @param registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        //注册一个STOMP的endpoint,并指定使用SockJS协议
        registry.addEndpoint("/chat").withSockJS();
    }
}

ChatController类 

用来处理更新在线人数  点对点实时消息发送

@Controller
public class ChatController {
    @Autowired
    SimpMessagingTemplate template;

    /**
     * 登录的controller
     * @param username
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/login")
    public void login(String username, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //维护一个在线人员的列表
        Contains.list.add(username);
        //把当前登录人存到session
        request.getSession().setAttribute("uname",username);
        response.sendRedirect("main.html");
    }

    /**
     * 获取当前登录的用户信息
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/userInfo")
    @ResponseBody
    public String login(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String info = request.getSession().getAttribute("uname").toString();
        return "{\"info\":\""+info+"\"}";
    }


    /**
     * server 更新在线人数列表的方法
     * 他会给所有订阅了/topic/userList的ws客户端发送消息
     * @return
     */
    @RequestMapping("/userList")
    @ResponseBody
    public String userList(){
        String allUser="";
        for (String s : Contains.list) {
            allUser+=s+",";
        }
        allUser =   allUser.substring(0,allUser.length()-1);
        template.convertAndSend("/topic/userList",allUser);
        return "success";
    }


    /**
     * 客户端发送消息方法
     * @param message
     * @param username
     * @return
     */
    @RequestMapping("/chatInfo")
    @ResponseBody
    public String chat(String message,String username){
        System.out.println("-------------------"+message+"---"+username);

        template.convertAndSendToUser(username,"chat",message);
        return  "success";
    }

}

Application类  

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

}

前端界面就不展示,毕竟是简单的实现,把主要的js代码贴上来。

chat.html的 js代码:

<script>
	var sendToname ="";//发送给谁
    var info = "";//自己是誰

    $(function() {



        sendToname = parent.$("#sendUsername").val();
        info = parent.$("#loginName").val();

        $("#header").text(sendToname); //设置聊天信息的人
        $("#sendButton").click(function () {
            var chatMsg = $("#sendVal").val();
            $.ajax({
                url: "/chatInfo",// 发送聊天信息给对应的人
                type: "post",
				data:'message='+chatMsg+'&username='+sendToname,
                dataType: "json",
                success: function (data) {

                }
            });
        });




        var socket = new SockJS('/chat');

        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {

            //订阅聊天的消息,发给我
            stompClient.subscribe('/user/'+info+"/chat", function (data) {
                console.log("我收到信息了----------"+data.body);
                initChatData(data.body);
            });

        });

    })

    function initChatData (messgae) {

		//动态添加聊天信息
        $("#content").append(" <li ><div class=\"msg\">"+messgae+"</div></li>");

    };

</script>

contacts.html的 js代码:

<script>
    //JavaScript代码区域
    layui.use('element', function(){
        var element = layui.element;
        // element.render("nav");
    });
    var info="";

    $(function(){

        $.ajax({
            url:"/userInfo",//发送在线人数给所有客户端
            type:"post",
            dataType:"json",
            success:function(data){
                console.log("当前登录的用户:"+data);
                info=data.info;
                $("#loginName").val(data.info); //存下当前登录的名字
            }

        });
        //连接ws
        var socket = new SockJS('/chat');
        stompClient = Stomp.over(socket);
        stompClient.connect({}, function (frame) {
            //订阅-------获取在线人数
            stompClient.subscribe('/topic/userList', function (data) {
                initOnLine(data.body)
            });
           /* //訂閲  聊天的消息,發給我
            stompClient.subscribe('/user/'+info+"/chat", function (data) {
                console.log("当前"+info+"我收到的消息:"+data);
            });*/
            $.ajax({
                url:"/userList",//发送在线人数给所有客户端
                type:"post",
                dataType:"json",
                success:function(data){

                }

            })
        });



    })


    function chat(obj){

        //把sendToUserName存到一个input
        $("#sendUsername").val(obj);

        layui.use('layer', function() {
            layer.open({
                area: ['700px', '900px'],
                type: 2,
                content: 'chat.html',
                maxWidth: 600,
            });
        });

    }
    function initOnLine(data){
        //user1,user2,user3,user4
        data = data.split(",");
        //[user1,user2.....]
        $("#onLine").html("");

        $.each(data,function(i,v){
            if (info==v){
                //如果当前登录的是自己,则标注是(自己)
                $("#onLine").append(" <li class=\"layui-nav-item\"><a href=\"javascript:chat(\'"+v+"\')\">"+v+' (自己)'+"</a></li>");
            }else {
                $("#onLine").append(" <li class=\"layui-nav-item\"><a href=\"javascript:chat(\'"+v+"\')\">"+v+"</a></li>");
            }


        })
    }
</script>

代码比较简单,上面都有注释,有问题谢谢指正。

相关标签: maven websocket