1.WebSocket介绍
Spring Boot 结合 WebSocket 实现在线聊天:https://mp.weixin.qq.com/s/Rrj7oco3K8kJBsTxEEdz9g
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。
为什么需要 WebSocket?
初次接触 WebSocket 的人,都会问同样的问题:我们已经有了 HTTP 协议,为什么还需要另一个协议?它能带来什么好处?
答案很简单,因为 HTTP 协议有一个缺陷:通信只能由客户端发起,HTTP 协议做不到服务器主动向客户端推送信息。
https://blog.csdn.net/moshowgame/article/details/80275084
2.SpringBoot结合WebSocket
群聊,不存在用户信息
依赖:web,socket
web-jar:在SSM,想使用前端库也可以像依赖一样添加到
https://mvnrepository.com/
https://mvnrepository.com/artifact/org.webjars/sockjs-client/1.1.2
sockjs-client
<!-- https://mvnrepository.com/artifact/org.webjars/sockjs-client -->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.1.2</version>
</dependency>
STOMP WebSocket » 2.3.3
JQuery » 3.5.1
Webjars Locator Core » 0.46(用来定位这些jar应该在哪里找)
HTTP状态码之101:https://juejin.cn/post/6844903959023321101
@Configuration
@EnableWebSocketMessageBroker//开启允许websocket代理
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
//配置消息代理:设置消息代理的前缀,如果发送的消息的前缀是/topic,则会将这个消息转发给消息代理Broker,消息代理再广播给所有连上来的客户端
//服务端广播的时候,消息前缀为topic
//registry.enableSimpleBroker("/topic");//群发
//也可以自己转发消息
//定义消息前缀
//registry.setApplicationDestinationPrefixes("/app")
registry.enableSimpleBroker("/topic","/queue");///topic用法做群发消息,/queue用来做点对点的消息发送,增强单聊功能
}
//用来注册端点
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
//定义了一个前缀为/chat的point,开启socketJS的支持,socketjs可解决浏览器对websocket的兼容性问题,客户端通过配置建立websocket连接
registry.addEndpoint("/chat").setAllowedOriginPatterns("http://localhost:8080").withSockJS();
}
}
@Configuration
@EnableWebSocketMessageBroker
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//配置密码编码器
@Bean
PasswordEncoder passwordEncoder(){//注册编码方案
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {//配置用户名密码
auth.inMemoryAuthentication().//在内存中
withUser("javaboy").password("$2a$10$hUj224jgRE/3aPzAJHpEseDnjGuRWaqgw808l9qNSEXclJW20Xjdy").roles("admin")//123
.and()
.withUser("hanjinyue").password("$2a$10$hUj224jgRE/3aPzAJHpEseDnjGuRWaqgw808l9qNSEXclJW20Xjdy").roles("user");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()//其余url的只要登录就能访问
.and()
.formLogin()//表单登录
.permitAll()//登录请求直接通过
.and()
.csrf()
.disable();//关闭csrf攻击
}
}
@Controller
public class GreetingController {
@Autowired
SimpMessagingTemplate simpMessagingTemplate;//单聊要用这个发送
//建立连接之后,客户端给服务器端发送消息的地址
@MessageMapping("/hello")
@SendTo("/topic/greeting")//服务器端广播转发,客户端(前端页面)对这个地址的消息监听,所有的客户端(前端)都将接收到这个消息
public Message greeting(Message msg){
System.out.println("服务器端广播");
System.out.println(msg.toString());
return msg;//转发这个消息
}
@MessageMapping("/online_chat")
public void chat(Principal principal, Chat chat){
String from = principal.getName();//principal用来获取当前谁登录的,也就是登录信息
chat.setFrom(from);//从登录信息中获取谁发送的消息,而不是从chat中
simpMessagingTemplate.convertAndSendToUser(chat.getTo(),"/queue/chat",chat);
}
}
11-03 在线私聊
单聊存在用户的概念,点对点聊天,把Spring Security整合进来
<script>
var stompClient;
$(function () {
connect();
$("#send").click(function () {
stompClient.send("/online_chat", {}, JSON.stringify({
'to': $("#username").val(),
'content': $("#content").val()
}))
})
})
function connect() {
var socketjs = new SockJS("/chat");
stompClient = Stomp.over(socketjs);
stompClient.connect({}, function (frame) {
stompClient.subscribe("/user/queue/chat", function (greeting) {//再固定的url前面加上/user
var msgContent = JSON.parse(greeting.body);
console.log(msgContent);
$("#chat").append("<div>" + msgContent.to + ":" + msgContent.content + "</div>");
});
})
}
</script>