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收不到消息
可以使用多个浏览器多个用户进行测试,同一个浏览器无法达到效果