SpringBoot整合WebSocket实现单聊(群聊)

springbootwebSocket实现群聊

1、创建项目导入依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--websocket依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <!--下面是前端需要的依赖-->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
        </dependency>

2、实体类

public class Message {
    private String name; //表示发消息的用户
    private String content;//表示消息内容
    //省略get、set方法
}

3、编写WebSocketConfig 配置类

WebSocketConfig 类实现WebSocketMessageBrokerConfigurer接口

@Configuration
@EnableWebSocketMessageBroker //开启WebSocket消息代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    //配置消息代理
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        //设置消息代理的前缀,如果消息的前缀为/topic,会将消息先转发到消息代理
        //再由消息代理广播给所有连接大客户端
        registry.enableSimpleBroker("/topic");
        //发送到/topic的表示群聊,发送到/queue 表示单聊
        //registry.enableSimpleBroker("/topic","/queue");
        //表示配置一个或多个前缀,通过这些前缀过滤出需要被注解的方法处理的消息
        registry.setApplicationDestinationPrefixes("/app");
    }
    //注册连接点
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat").withSockJS();
    }
}

4、编写controller

@Controller
public class GreetingController {
    //WebSocket提供的消息发送的模板 可以替代@SendTo("/topic/greetings")
    @Autowired
    SimpMessagingTemplate simpMessagingTemplate;
    //实现群聊
    /*@MessageMapping("/hello") //表示这个方法用来处理浏览器发送来的消息
    @SendTo("/topic/greetings")//对消息处理完后再进行转发
    public Message greeting(Message message){
        System.out.println(message);
        return message;
    }*/
    //与上边的方法一致
    @MessageMapping("/hello") //表示这个方法用来处理浏览器发送来的消息
    public void greetingT(Message message){
        System.out.println(message);
        simpMessagingTemplate.convertAndSend("/topic/greetings",message);
    }   
}

5、前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>群聊</title>
    <!--导入需要的js文件-->
    <script src="/webjars/jquery/3.4.1/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/1.1.2/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/2.3.3/stomp.min.js"></script>
</head>
<body>
<table>
    <tr>
        <td>请输入用户名</td>
        <td><input type="text" id="name"></td>
    </tr>
    <tr>
        <td><input type="button" id="connect" value="连接"></td>
        <td><input type="button" id="disconnect" disabled="disabled" value="断开连接"></td>
    </tr>
</table>
<div id="chat" style="display: none">
    <table>
        <tr>
            <td>请输入聊天内容</td>
            <td><input type="text" id="content"></td>
            <td><input type="button" id="send" value="发送"></td>
        </tr>
    </table>
    <div id="conversation">群聊进行中......</div>
</div>
​
<script>
    $(function () {
        $("#connect").click(function () {
            connect();
        });
        $("#disconnect").click(function () {
            if(stompClient != null){
                stompClient.disconnect();
            }
            setConnected(false);
        });
        //与后端WebSocketConfig 配置类相对应,表示消息要通过controller层处理
        $("#send").click(function () {
            stompClient.send('/app/hello',{},JSON.stringify({'name':$("#name").val(),'content':$("#content").val()}))
        })
    });
    var stompClient = null;
   //该方法表示连接服务
    function connect() {
        if (!$("#name").val()){
            alert("请输入用户名")
        }
        var socket = new SockJS('/chat');
        stompClient = Stomp.over(socket);
        //第一个参数表示基本配置(优先级之类的),第二个参数表示连接成功后的一个回调函数
        stompClient.connect({},function (success) {
            setConnected(true);
            //订阅服务器上的消息
            stompClient.subscribe('/topic/greetings',function (msg) {
               showGreeting(JSON.parse(msg.body))
​
            });
        });
    }
    //该方法表示展示发送的消息内容
    function showGreeting(msg) {
        $("#conversation").append('<div>' + msg.name +':'+msg.content + '<div>');
    }
    //该方法表示改变按钮的状态
    function setConnected(flag) {
        $("#connect").prop("disabled",flag);
        $("#disconnect").prop("disabled",!flag);
        if (flag){
            $("#chat").show();
        }else{
            $("#chat").hide();
        }
    }
</script>
</body>
</html>

配置完成,开始群聊

初始状态

 

输入用户名点击连接后状态改变:

 

打开另外一个浏览器进行聊天:这里分别使用谷歌浏览器和ie浏览器

 

springbootwebSocket实现单聊

实现单聊就要比群聊复杂一些,需要引入角色的概念,

所以在上述依赖的基础上引入security依赖

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

添加SecurityConfig配置类:

在内存中加载两个角色用户,以及配置登录拦截

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder(){
        //提供密码不加密的实例
        return NoOpPasswordEncoder.getInstance();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //在内存中设置两个角色用户
        auth.inMemoryAuthentication()
                .withUser("admin").password("123").roles("admin")
                .and()
                .withUser("user").password("123").roles("user");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //http.authorizeRequests().anyRequest().authenticated()
        //表示所有请求都需要登录后才可以访问
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin().permitAll();
    }
}

WebSocketConfig 配置类修改

registry.enableSimpleBroker("/topic");

将上面设置改为:

 //发送到/topic的表示群聊,发送到/queue 表示单聊
 registry.enableSimpleBroker("/topic","/queue");

controller层加入新的方法用来处理单聊

 //实现单聊
    @MessageMapping("/chat")
    public void chat(Principal principal, Chat chat){
        System.out.println(chat);
        //Principal保存的是用户信息
        //表示获取登录用户,消息是从哪里发出的
        chat.setFrom(principal.getName());
        //参数分别为,要发送的用户、消息服务器、消息对象
        simpMessagingTemplate.convertAndSendToUser(chat.getTo(),"/queue/chat",chat);
​
    }

chat的实体类:

public class Chat {
    //三个参数分别表示消息从哪里来,消息内容、消息到哪里去
    private String from;
    private String content;
    private String to;
    //省略get、set方法
}
onlinechat.html界面:
基本与群聊相似,要注意在订阅服务器上的消息的时候的请求连接
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>单聊</title>
    <script src="/webjars/jquery/3.4.1/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/1.1.2/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/2.3.3/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" id="send" value="发送">
<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/前缀
            //此处可与群聊订阅做对比
            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>

开始单聊:

可以看到admin和user可以互相发送消息

 

改变目标用户查看效果:

 

可以看到控制台打印了发送的目标用户以及消息内容,目标用户为user1,所有user收不到消息

可以使用多个浏览器多个用户进行测试,同一个浏览器无法达到效果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值