SpringBoot整合WebSocket
SpringBoot整合WebSocket
一、springboot实现在线群聊
1、pom.xml
主要的后端依赖
spring-boot-starter-websocket
前端依赖
sockjs-client
jquery
stomp-websocket
webjars-locator-core
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.lc</groupId>
<artifactId>websocket1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>websocket1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--前端websocket客户端依赖-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.1.2</version>
</dependency>
<!--jquery-->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、消息bean
@Getter
@Setter
public class Message {
private String name;
private String content;
}
3、websocket代理服务器
/**
* 实现websocket消息代理人配置器
*/
@Configuration
//开启消息代理
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 消息代理的前缀
registry.enableSimpleBroker("/topic");
registry.setApplicationDestinationPrefixes("/app");
}
/**
* 建立连接点
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
}
4、消息请求处理controller
@Controller
public class GreetingController {
// 处理客户端请求消息的路径
//客户端发送消息的路径 /app/hello
@MessageMapping("/hello")
// 服务器广播的路径(/topic/greetings) 由配置的topic前缀的服务去处理
//客户端订阅消息的路径 /topic/greeting
@SendTo("/topic/greetings")
public Message greeting(Message message) {
return message;
}
}
5、聊天页面
<!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>
<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" value="断开连接" disabled="disabled"/></td>
</tr>
</table>
<!--display:none 此块不会显示-->
<div id="chat" style="display: none;">
<table>
<tr>请输入聊天内容</tr>
<td><input type="text" id="content"/></td>
<td><input type="button" id="send" value="发送"></td>
</table>
<div id="conversation">群聊进行中....</div>
</div>
<script>
$(function () {
//点击连接
$("#connect").click(function () {
connect()
});
// 断开连接
$("#disconnect").click(function () {
if(stompClient!=null){
//直接断开连接
stompClient.disconnect();
}
setConnect(false);
});
$("#send").click(function () {
stompClient.send('/app/hello',{},JSON.stringify({'name':$("#name").val(),'content':$("#content").val()}))
})
})
var stompClient=null;
//尝试连接
function connect() {
//如果没有输入用户名 直接返回
if(!$("#name").val()){
alert("请输入用户名")
return;
}
//建立连接点
var socket=new SockJS('/chat');
stompClient=Stomp.over(socket);
stompClient.connect({},function (success) {
//连接成功的回调
//建立连接 (界面的处理)
setConnect(true);
// 订阅服务器的消息(后端服务服务器广播消息的路径)
stompClient.subscribe('/topic/greetings',function (msg) {
//服务端的msg的具体消息 在body属性中
//将字符串消息转为json对象
showGreeting(JSON.parse(msg.body))
})
},function () {
// 连接失败的回调
})
}
//展示消息
function showGreeting(msg) {
//向聊天div中追加内容
$("#conversation").append('<div>'+msg.name+":"+msg.content+'</div>')
}
//建立连接
function setConnect(flag) {
//prop() 方法设置或返回被选元素的属性和值。
//如果连接成功 则设置 '连接' 按钮不可用
$("#connect").prop("disabled",flag);
//断开连接按钮 可用
$("#disconnect").prop("disabled",!flag);
if (flag) {
//显示 聊天界面
$("#chat").show();
}else{
$("#chat").hide();
}
}
</script>
</body>
</html>
二、 springboot实现在线单聊
1、pom.xml
主要的后端依赖
spring-boot-starter-websocket
spring-boot-starter-security
前端依赖
sockjs-client
jquery
stomp-websocket
webjars-locator-core
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.lc</groupId>
<artifactId>websocket1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>websocket1</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!--前端websocket客户端依赖-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.1.2</version>
</dependency>
<!--jquery-->
<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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、消息bean
@Getter
@Setter
public class Chat {
/**
* 消息从哪来
*/
private String from;
/**
* 消息内容
*/
private String content;
/**
* 消息发给谁
*/
private String to;
}
3、websocket代理服务器
/**
* 实现websocket消息代理人配置器
*/
@Configuration
//开启消息代理
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
// 消息代理的前缀
// 在这里我们定义 /topic为群聊消息 /queue为单聊消息
registry.enableSimpleBroker("/topic","/queue");
// 定义程序的发送目标前缀
registry.setApplicationDestinationPrefixes("/app");
}
/**
* 建立连接点
* @param registry
*/
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/chat").withSockJS();
}
}
4、security配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("lc")
.password("123")
.roles("admin")
.and()
.withUser("zs")
.password("123")
.roles("user");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().
anyRequest().authenticated()
.and()
.formLogin()
// 允许所有登录请求
.permitAll();
}
}
5、消息请求处理controller
@Controller
public class GreetingController {
// // 处理客户端请求消息的路径
// @MessageMapping("/hello")
//// 服务器广播的路径(/topic/greetings) 由配置的topic前缀的服务去处理
// @SendTo("/topic/greetings")
// public Message greeting(Message message) {
// return message;
// }
/**
* 使用消息发送模板
*/
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
@MessageMapping("/hello")
public void greeting(Message message) {
// 直接指定发送的路径和消息
simpMessagingTemplate.convertAndSend("/topic/greetings",message);
}
/**
* 单聊
* @param principal 当前登录的用户信息
* @param chat
*/
@MessageMapping("/chat")
public void chat(Principal principal, Chat chat) {
//谁发的消息 (指定发送人)
chat.setFrom(principal.getName());
// 指定发送人 ,发送的路径 ,发送的消息
simpMessagingTemplate.convertAndSendToUser(chat.getTo(), "/queue/chat", chat);
}
}
6、聊天页面
注意:
// 注意在单聊是 发送给指定用户,那么websocket服务端自动帮我们加 /user 所以这里我们也要加 /user
stompClient.subscribe('/user/queue/chat', function (msg) {
//服务端的msg的具体消息 在body属性中
//将字符串消息转为json对象
showGreeting(JSON.parse(msg.body))
})
<!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" value="断开连接" disabled="disabled"/>
<hr>
<table>
<tr>
<td>消息内容:</td>
<td><input type="text" id="content"></td>
</tr>
<tr>
<td>目标用户:</td>
<td><input type="text" id="to"></td>
</tr>
<tr>
<td><input type="button" value="发送" id="send"></td>
</tr>
</table>
<div id="chat" style="display: none">
<div id="conversation">连接进行中...</div>
</div>
<script>
$(function () {
//点击连接
$("#connect").click(function () {
connect()
});
// 断开连接
$("#disconnect").click(function () {
if (stompClient != null) {
//直接断开连接
stompClient.disconnect();
}
setConnect(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) {
//连接成功的回调
//建立连接 (界面的处理)
setConnect(true);
// 订阅服务器的消息
// 注意在单聊是 发送给指定用户,那么websocket服务端自动帮我们加 /user 所以这里我们也要加 /user
stompClient.subscribe('/user/queue/chat', function (msg) {
//服务端的msg的具体消息 在body属性中
//将字符串消息转为json对象
showGreeting(JSON.parse(msg.body))
})
}, function () {
// 连接失败的回调
})
}
//展示消息
function showGreeting(msg) {
//向聊天div中追加内容
$("#conversation").append('<div>' + msg.from + ":" + msg.content + '</div>')
}
//建立连接
function setConnect(flag) {
//prop() 方法设置或返回被选元素的属性和值。
//如果连接成功 则设置 '连接' 按钮不可用
$("#connect").prop("disabled", flag);
//断开连接按钮 可用
$("#disconnect").prop("disabled", !flag);
if (flag) {
//显示 聊天界面
$("#chat").show();
} else {
$("#chat").hide();
}
}
</script>
</body>
</html>