热门IT资讯网

基于SpringBoot和WebSocket实现简易聊天室

发表于:2024-11-28 作者:热门IT资讯网编辑
编辑最后更新 2024年11月28日,今天小编就为大家带来一篇使用SpringBoot和WebSocket实现简易聊天室的文章。小编觉得挺不错的,为此分享给大家做个参考。一起跟随小编过来看看吧。①:什么是 WebSocket?WebSoc

今天小编就为大家带来一篇使用SpringBoot和WebSocket实现简易聊天室的文章。小编觉得挺不错的,为此分享给大家做个参考。一起跟随小编过来看看吧。

①:什么是 WebSocket?

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议

根据这个定义有两个注意的地方:

协议就是相互通信的计算机双方必须共同遵守的一组约定。

1)HTTP协议基于 TCP 协议,建立链接必须通过三次握手才能发送信息。

2)http链接分为短链接,长链接,短链接是每次请求都要三次握手才能发送自己的信息。即每一个request 对应一个 response。长链接是在一定的期限内保持链接。保持TCP连接不断开。客户端与服务器通信,必须要有客户端发起然后服务器返回结果。客户端是主动的,服务器是被动的。

3)WebSocket 他是为了解决客户端发起多个 http 请求到服务器资源浏览器必须要经过长时间的轮训问题而生的,他实现了多路复用,他是全双工通信。在 webSocket 协议下客服端和浏览器可以同时发送信息。

②:使用基于STOMP协议的WebSocket+Springboot实现简易聊天室
@Configuration@EnableWebSocketMessageBroker   //通过此注解开启 WebSocket 消息代理public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {    @Override    public void configureMessageBroker(MessageBrokerRegistry config) {        //设置消息代理的前缀        // 如果消息的前缀是 /topic 就会将消息转发给消息代理(broker)再由消息代理转发给所有连接的客户端        config.enableSimpleBroker("/topic");    //客户端接收服务端消息的地址前缀        //配置一个或多个前缀,通过这些前缀过滤出需要被注解方法处理的消息。        // 例如前缀为"/app"的 destination 可以通过 @MessageMapping 注解的方法处理,而其他 destination("/topic","/query") 将被直接交给 broker 处理        config.setApplicationDestinationPrefixes("/app");   //客户端给服务端发消息的地址前缀    }    @Override    public void registerStompEndpoints(StompEndpointRegistry registry) {        //定义一个前缀为 "chat" 的endpoint,并开启 sockJs支持。        // sockJs 可以解决对 WebSocket 的兼容性问题,客户端将通过这里配置的 url 建立 WebSocket 连接        registry.addEndpoint("/chat").withSockJS();    }}
@Controllerpublic class GreetingController {    /**     * 执行步骤:     *  1,由 WebSocketConfig 中的配置,@MessageMapping 注解接收 "/app/hello" 路径发来的消息     *  2,注解方法对消息进行处理后,将消息转发到 @SendTo 定义的路径上     *  3,@SendTo 定义的路径是一个前缀为 "/topic" 的路径,由配置文件,此消息将被交给消息代理 broker,由 broker 进行广播     * @param message     * @return     */    @MessageMapping("/hello")    @SendTo("/topic/greetings")    public Message greeting(Message message) {        return message;    }}
        群聊                    
群聊进行中
var stompClient = null;//页面显示设置function setConnected(connected) {    $("#connect").prop("disabled", connected);    $("#disconnect").prop("disabled", !connected);    if (connected) {        $("#conversation").show();        $("#chat").show();    } else {        $("#conversation").hide();        $("#chat").hide();    }    $("#greeting").html("");}//建立一个 WebSocket 连接,建立连接之前必须输入用户名function connect() {    if (!$("#name").val()) {        return;    }    //创建一个 SockeJS 实例    var socket = new SockJS('/chat');    //使用stomp.over方式创建一个stompClient,完成客户端的创建。    stompClient = Stomp.over(socket);    stompClient.connect({}, function (frame) {        //进行页面设置        setConnected(true);        //使用 subscribe 方法订阅服务端发送回来的消息,并将服务端发送的消息展示出来        stompClient.subscribe('/topic/greetings', function (greetings) {            showGreeting(JSON.parse(greetings.body));        })    })}//断开 WebSocket 连接function disconnect() {    if (stompClient != null) {        stompClient.disconnect();    }    setConnected(false)}//发送信息function sendName() {    stompClient.send("/app/hello", {},        JSON.stringify({'name': $('#name').val(), 'content': $('#content').val()}));}//展示信息function showGreeting(message) {    $('#greetings')        .append("
" + message.name + ":" + message.content + "
")}$(function () { //建立连接 $("#connect").click(function () { connect(); }); //断开连接 $("#disconnect").click(function () { disconnect(); }); //发送信息 $("#send").click(function () { sendName(); });})

1)maven 引入依赖错误(尽量去 maven 的中央仓库拷贝依赖)

2)stomp 协议的引入

    使用STOMP的好处在于,它完全就是一种消息队列模式,你可以使用生产者与消费者的思想来认识它,发送消息的是生产者,接收消息的是消费者。而消费者可以通过订阅不同的destination,来获得不同的推送消息,不需要开发人员去管理这些订阅与推送目的地之前的关系。

案例见spring官网就有一个简单的spring-boot的stomp-demo,如果是基于springboot,大家可以根据spring上面的教程试着去写一个简单的demo。

③:换种方式实现群发消息
    /**     *  1. @MessageMapping("/hello") Spring提供一个 @MessageMapping 注解实现了对 WebScoket 的封装     *  2. SimpMessagingTemplate 是 Spring-WebSocket 内置的一个消息发送的工具     * @param message     * @throws Exception     */    @Autowired    private SimpMessagingTemplate simpMessagingTemplate;    @MessageMapping("/hello")    public void  greeting(Message message) throws Exception{        //使用这个方法进行消息的转发发送        simpMessagingTemplate.convertAndSend("/topic/greetings",message);    }
④:实现点对点通信

刚刚实现的功能是群发消息,下面看下私聊是如何实现的。点对点通信需要配置多个用户,我们用 SpringSecurity 添加两个用户。

            org.springframework.boot        spring-boot-starter-security    
@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter {    @Bean    PasswordEncoder passwordEncoder() {        return new BCryptPasswordEncoder();    }    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        auth.inMemoryAuthentication()                //添加两个用户 admin,sang,密码设为123。                .withUser("admin")                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")                .roles("admin")                .and()                .withUser("sang")                .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")                .roles("user");    }    @Override    protected void configure(HttpSecurity http) throws Exception {        http.authorizeRequests()                .anyRequest().authenticated()                .and()                .formLogin().permitAll();    }}
@Configuration@EnableWebSocketMessageBroker   //通过此注解开启 WebSocket 消息代理public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {    @Override    public void configureMessageBroker(MessageBrokerRegistry config) {        //客户端接收服务端消息的地址前缀        //在群发的基础上,添加一个客户端接收地址的前缀。        config.enableSimpleBroker("/topic","/queue");           //客户端给服务端发消息的地址前缀        config.setApplicationDestinationPrefixes("/app");    }    @Override    public void registerStompEndpoints(StompEndpointRegistry registry) {        //定义一个前缀为 "chat" 的endpoint,并开启 sockJs支持。        // sockJs 可以解决对 WebSocket 的兼容性问题,客户端将通过这里配置的 url 建立 WebSocket 连接        registry.addEndpoint("/chat").withSockJS();    }}
@Controllerpublic class GreetingController {    @Autowired    private SimpMessagingTemplate simpMessagingTemplate;    //群发消息使用 @SendTo 注解    @MessageMapping("/hello")    @SendTo("/topic/greetings")    public Message greeting(Message message) throws Exception{        return message;    }    //点对点发送消息使用 SimpMessagingTemplate 实现    @MessageMapping("/chat")    //来自 "/app/chat" 的消息将会被此方法处理    public void chat(Principal principal, Chat chat)throws Exception{        String from = principal.getName();        chat.setFrom(from);        simpMessagingTemplate.convertAndSendToUser(chat.getTo(),"/queue/chat",chat);    }}
        群聊                    
请输入聊天内容: 目标用户:
var stompClient = null;//建立一个 WebSocket 连接,建立连接之前必须输入用户名function connect() {    //创建一个 SockeJS 实例    var socket = new SockJS('/chat');    stompClient = Stomp.over(socket);    stompClient.connect({}, function (frame) {        //使用 subscribe 方法订阅服务端发送回来的消息,并将服务端发送的消息展示出来        stompClient.subscribe('/user/queue/chat', function (chat) {            showGreeting(JSON.parse(chat.body));        })    })}//发送信息function sendMsg() {    stompClient.send("/app/chat", {},        JSON.stringify({'content': $('#content').val(), 'to': $('#to').val()}));}//展示信息function showGreeting(message) {    $('#chatsContent')        .append("
" + message.from + ":" + message.content + "
")}$(function () { connect(); $('#send').click(function () { sendMsg(); });})

演示效果时请使用不同用户登录的同一浏览器或者不同浏览器演示




关于使用SpringBoot和WebSocket实现简易聊天室的代码分享就到这了,详细使用情况还需要大家自己使用过才领会。如果想了解更多相关内容,欢迎关注行业资讯频道!

0