WebSocket快速入门
这里重点记录WebSocket的入门以及和SpringBoot的整合。
文章目录
一、WebSocket是什么?
WebSocket 是HTML5一种新的协议。它实现了浏览器与服务器全双工通信(full-duplex)。一开始的握手需要借助
HTTP请求完成。 WebSocket是真正实现了全双工通信的服务器向客户端推的互联网技术。 它是一种在单个TCP连
接上进行全双工通讯协议。Websocket通信协议与2011年倍IETF定为标准RFC 6455,Websocket API被W3C定为
标准
原理图:WebSocket协议是一种长链接,只需要通过一次请求来初始化链接,然后所有的请求和响应都是通过这个TCP链接
进行通讯。
浏览器支持:
服务器支持Tomact7以上。
二、使用步骤
(一)服务端入门
1.注解介绍
@ServerEndpoint("/websocket/{uid}")
申明这是一个websocket服务
需要指定访问该服务的地址,在地址中可以指定参数,需要通过{}进行占位
@OnOpen
用法:public void onOpen(Session session, @PathParam(“uid”) String uid) throws
IOException{}
该方法将在建立连接后执行,会传入session对象,就是客户端与服务端建立的长连接通道
通过@PathParam获取url申明中的参数
@OnClose
用法:public void onClose() {}
该方法是在连接关闭后执行
@OnMessage
用法:public void onMessage(String message, Session session) throws IOException {}
该方法用于接收客户端发来的消息
message:发来的消息数据
session:会话对象(也是通道)
发送消息到客户端
用法:session.getBasicRemote().sendText(“你好”);
通过session进行发送
2.导入依赖
代码如下(示例):
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dbh123.websocket</groupId>
<artifactId>WebSocketTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source><target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8082</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.创建测试类
代码如下(示例):
package com.dbh123.websocket;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
@ServerEndpoint("/mySocket/{id}")
public class MyWebSocketTest {
/**
* 为建立连接后调用方法
* @param session
* @param id 客服端传过来的参数
*/
@OnOpen
public void onOpen(Session session , @PathParam("id")String id){
System.out.println(id + ",连接已建立");
}
/**
* 收到信息后调用方法
* @param message 接受的信息
* @param session
*/
@OnMessage
public void onMessage(String message , Session session) throws IOException {
System.out.println("接受到消息 -->" + message);
//向客服端传递消息
session.getBasicRemote().sendText("已经收到消息");
}
/**
* 连接关闭后调用方法
*/
@OnClose
public void onClose(){
System.out.println("连接已断开");
}
}
(二)客户端入门
编写客户端页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket</title>
</head>
<script>
//WebSocket为浏览器自己的类所以不用导入任何包
//创建socket对象
const socket = new WebSocket("ws://localhost:8082/mySocket/520");
//建立连接调用方法
socket.onopen = (ws) => {
console.log("连接已建立" , ws);
}
//收到消息调用方法
socket.onmessage = (ws) =>{
console.log("接收到消息 >> ",ws.data);
}
//断开连接调用方法
socket.onclose = (ws) =>{
console.log("连接已断开!", ws);
}
//连接错误调用方法
socket.onerror = (ws) => {
console.log("发送错误!", ws);
}
// 2秒后向服务端发送消息
setTimeout(()=>{
socket.send("Hellow , WebSocket");
},2000);
// 5秒后断开连接
setTimeout(()=>{
socket.close();
},5000)
</script>
<body>
</body>
</html>
三、Springboot整合WebSocket
1.导入pom依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
</parent>
<dependencies>
<!--<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>-->
<!--Springboot依赖整合了WebSocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
</dependencies>
2.编写WebSocketHandler类
package com.dbh123.websocket.spring;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
@Component
public class MyWebSocketHandler extends TextWebSocketHandler {
/**
* 建立连接之后调用
* @param session
* @throws Exception
*/
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
System.out.println("连接已建立");
}
/**
* 接受消息之后调用
* @param session
* @param message
* @throws Exception
*/
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
System.out.println("收到消息 --> " + message.getPayload());
//发送消息
session.sendMessage(new TextMessage("消息已收到"));
}
/**
* 断开连接后调用
* @param session
* @param status
* @throws Exception
*/
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("断开连接");
}
}
3.注册WebSocketHandler类
package com.dbh123.websocket.config;
import com.dbh123.websocket.spring.MyWebSocketHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketCOnfig implements WebSocketConfigurer {
@Autowired
MyWebSocketHandler myHander;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
//第一个参数为拦截器 第二个为访问地址 setAllowedOrigins为支持跨域的范围
webSocketHandlerRegistry.addHandler(myHander, "/ws").setAllowedOrigins("*");
}
}
注意:对于微服务需要通过registry.addHandler(myHandler(), “/ws”).setAllowedOrigins("*")方法打开跨域请求。
4.WebSocketHandler拦截器
这是Springboot针对WebSocket设置的拦截器
(1)编写拦截器
package com.dbh123.websocket.spring.interceptor;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import java.util.Map;
public class MyHandShakeInterceptor implements HandshakeInterceptor {
/**
* 建立连接握手前访问
* @param serverHttpRequest
* @param serverHttpResponse
* @param webSocketHandler
* @param map 连接中Session中的键值对
* @return true:建立连接 false:拒绝连接
* @throws Exception
*/
@Override
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
//将用户id放入socket处理器的会话(WebSocketSession)中
map.put("uid", 1001);
System.out.println("开始握手。。。。。。。");
return true;
}
/**
* 握手后建立
* @param serverHttpRequest
* @param serverHttpResponse
* @param webSocketHandler
* @param e
*/
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
System.out.println("握手成功");
}
}
(2)注册拦截器
package com.dbh123.websocket.spring.config;
import com.dbh123.websocket.spring.MyWebSocketHandler;
import com.dbh123.websocket.spring.interceptor.MyHandShakeInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
@Configuration
@EnableWebSocket
public class WebSocketCOnfig implements WebSocketConfigurer {
@Autowired
MyWebSocketHandler myHander;
@Autowired
MyHandShakeInterceptor myHandShakeInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) {
//第一个参数为拦截器 第二个为访问地址 setAllowedOrigins为支持跨域的范围
webSocketHandlerRegistry.addHandler(myHander, "/ws").setAllowedOrigins("*")
.addInterceptors(myHandShakeInterceptor);
}
}