http协议是短链接,因为请求之后,都会关闭连接,下次重新请求数据,需要再次打开链接
1.定义 :WebSocket 是HTML5的新协议,它实现了浏览器与服务器全双工通信(full-duplex),一开始的握手需要借助HTTP请求完成。WebSocket是真正实现了全双工通信的服务器项客户端推送的互联网技术。它是在一种单个TCP连接上进行全双工通讯协议。WebSocket通信协议与2011年被IEFT定为标准RFC6455,WebSocketAPI 被W3C定为标准。
查询支持的浏览器: https://caniuse.com/#search=websocket
服务端支持: Tomcat 7.0.47+以上才支持
websocket 的相关注解说明
@ServerEndpoint("/websocket/{uid}")
3.1 申请这是一个websocket服务
3.2 需要指定访问该服务的地址,在地址中可以指定参数,需要通过{}进行占位
@OnOpen
用法: public void onOpen(Session session,@PathParam(“uid”) String uid) throws IOException{}
该方法在建立连接后执行,会传入session对象,就是客户端与服务端建立的长连接通道
通过@PathParam获取Url申明的参数
@Close
用法:public void onClose(){}
该方法是在连接关闭后执行
@OnMessage
用法: public void onMessage(String message,Session session) throws IOException{}
该方法用于接收客户端发来的消息
message: 发来的消息数据
session:会话对象(也是通道)
发送消息到客户端
用法: session.getBasicRemote().sendText(“你好”)
通过session进行发送
快速入门
创建工程,引入依赖
<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>9082</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
创建类:com.sharpnew.websocket.MyWebSocket
编写实现类
@ServerEndpoint("/websocket/{uid}")
public class MyWebSocket {
/*
打开
*/
@OnOpen
public void onOpen(Session session,@PathParam("uid") String uid) throws IOException {
System.out.println("websocket已经连接" + session);
//给客户端响应,欢迎登录
session.getBasicRemote().sendText(uid+"欢迎登录系统");
}
/*
关闭
*/
@OnClose
public void onClose(Session session) {
System.out.println("websocket已经关闭" + session);
}
/*
客户发来消息
*/
@OnMessage
public void onMessage(String message, Session session) throws IOException {
System.out.println("收到客户端发来的消息--->" + message);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
session.getBasicRemote().sendText("消息已收到");
}
}
启动tomcat ,然后 maven Projects—> Plugins->tomcat7:run
在线测试工具:
http://www.easyswoole.com/wstool.html
<html>
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<script>
const socket = new WebSocket("ws://localhost:9082/websocket/1");
socket.onopen = (ws) => {
console.log("建立连接");
}
socket.onclose = (ws) => {
console.log("关闭连接");
}
socket.onmessage = (ws) => {
console.log("接收到消息", ws.data);
}
socket.onerror = (ws) => {
console.log("发送错误", ws);
}
setTimeout(()=>{
socket.send("发送一条消息试试");
},2000);
setTimeout(()=>{
socket.close();
},5000);
</script>
</html>
springBoot 整合WebSocket
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-websocket</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</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>
2.继承方法并重写
//注入容器中
@Component
public class MyHandler extends TextWebSocketHandler {
@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
System.out.println("获取到消息 >> " + message.getPayload());
session.sendMessage(new TextMessage("消息已收到"));
//当消息等于10,输出0-9
if (message.getPayload().equals("10")) {
for (int i = 0; i < 10; i++) {
session.sendMessage(new TextMessage("消息 -> " + i));
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
session.sendMessage(new TextMessage("欢迎连接到ws服务"));
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
System.out.println("断开连接!");
}
}
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private MyHandler myHandler;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//所有地址可以跨域setAllowedOrigins("*")
registry.addHandler(this.myHandler, "/ws").setAllowedOrigins("*");
}
}
4.编写启动类
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
websocket拦截器
在spring 中提供了websocket拦截器,可以在建立连接之前写些业务逻辑,比如验证登录等。
1.编写拦截器实现类
@Component
public class MyHandshakeInterceptor implements HandshakeInterceptor {
/*
握手之前,若返回false,则不建立连接
*/
@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
//将用户id放入socket处理器的会话(WebSocketSession)中
attributes.put("uid", 1001);
System.out.println("开始握手。。。。。。。");
return true;
}
@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse
serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {
System.out.println("握手成功............");
}
}
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
@Autowired
private MyHandler myHandler;
@Autowired
private MyHandshakeInterceptor myHandshakeInterceptor;
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
//所有地址可以跨域setAllowedOrigins("*")
registry.addHandler(this.myHandler, "/ws").setAllowedOrigins("*").addInterceptors(this.myHandshakeInterceptor);
}
}