一篇文章带你使用 SpringBoot 搞定基于WebSocket 的在线单聊实现

前面我们已经学习了 WebSocket 的在线群聊实现 本篇文章主要来学习使用 WebSocket 实现消息的一对一发送。

一、前期配置

前面依赖部分和 WebSocket 的在线群聊实现 的一致,不过这里还需要添加 Spring Security 的依赖:

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

二、配置 Chat 类

Chat 类用来承载服务器返回给浏览器的消息

public class Chat {
    
    
    private String from;//消息从哪来
    private String content;//消息内容
    private String to;//消息到哪去

    public String getFrom() {
    
    
        return from;
    }

    public void setFrom(String from) {
    
    
        this.from = from;
    }

    public String getContent() {
    
    
        return content;
    }

    public void setContent(String content) {
    
    
        this.content = content;
    }

    public String getTo() {
    
    
        return to;
    }

    public void setTo(String to) {
    
    
        this.to = to;
    }
}

三、配置 WebSocket

@Configuration
//开启使用STOMP协议来传输基于代理的消息,Broker就是代理的意思
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
    
    /**
     * 配置消息代理
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
    
    
        //定义消息代理的前缀,topic 表示群聊,queue 表示单聊
        registry.enableSimpleBroker("/topic","/queue");
        //配置一个或者多个前缀,过滤出需要代理方法处理的消息
        registry.setApplicationDestinationPrefixes("/app");
    }

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

四、配置控制器

这里多了个 Principal,也就是用户必须登录之后才可以聊,点对点聊必须要知道信息发给谁

@Controller
public class GreetingController {
    
    
    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;
    @MessageMapping("/hello")
    public void greeting(Message message) {
    
    
        simpMessagingTemplate.convertAndSend("/topic/greetings", message);
    }

    @MessageMapping("/chat")
    public void chat(Principal principal, Chat chat) {
    
    
        //消息从哪来
        chat.setFrom(principal.getName());
        //要发给谁,要发的地址,要发的对象
        simpMessagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);
    }
}

(1)SimpMessagingTemplate这个类主要是实现向浏览器发送消息的功能。
(2)在Spring MVC中,可以直接在参数中获取PrincipalPrincipal中包含有当前用户的用户名。
(3)convertAndSendToUser方法是向用户发送一条消息,第一个参数是目标用户用户名,第二个参数是浏览器中订阅消息的地址,第三个参数是消息本身。

五、配置 SecurityConfig

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    
    @Bean
    PasswordEncoder passwordEncoder() {
    
    
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    
    
        auth.inMemoryAuthentication()
                .withUser("yolo")
                .password("123")
                .roles("admin")
                .and()
                .withUser("nlcs")
                .password("123")
                .roles("user");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    
    
        http.authorizeRequests()
                //所有请求登录后访问
                .anyRequest().authenticated()
                .and()
                .formLogin().permitAll();
    }
}

六、配置 前端页面 onlineChat.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单聊</title>
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
</head>
<body>
<input type="button" id="connect" value="连接">
<input type="button" id="disconnect" disabled="disabled" value="断开连接">
<hr>
消息内容:<input type="text" id="content">目标用户:<input type="text" id="to"><input type="button" value="发送" id="send">
<div id="conversation"></div>
<script>
    $(function () {
    
    
        $("#connect").click(function () {
    
    
            connect();
        })
        $("#disconnect").click(function () {
    
    
            if (stompClient != null) {
    
    
                stompClient.disconnect();
            }
            setConnected(false);
        })

        $("#send").click(function () {
    
    
            stompClient.send('/app/chat', {
    
    }, JSON.stringify({
    
    
                'to': $("#to").val(),
                'content': $("#content").val()
            }))
        })
    })

    var stompClient = null;

    function connect() {
    
    
        var socket = new SockJS('/chat');
        stompClient = Stomp.over(socket);
        stompClient.connect({
    
    }, function (success) {
    
    
            setConnected(true);
            //订阅消息,需要加上 /user/,因为 WebSocket 后台调整时会自动加上该前缀
            stompClient.subscribe('/user/queue/chat', function (msg) {
    
    
                showGreeting(JSON.parse(msg.body));
            });
        })
    }

    function showGreeting(msg) {
    
    
        $("#conversation").append('<div>' + msg.from + ':' + msg.content + '</div>');
    }

    function setConnected(flag) {
    
    
        $("#connect").prop("disabled", flag);
        $("#disconnect").prop("disabled", !flag);
        if (flag) {
    
    
            $("#chat").show();
        } else {
    
    
            $("#chat").hide();
        }
    }
</script>
</body>
</html>

七、测试

只有登录用户才能互相通信

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/nanhuaibeian/article/details/108931972