赞
踩
问题:服务器无法直接向浏览器发送请求(HTTP协议的缺陷)
常见替代方案:轮询,浏览器给服务器不断地发送请求询问支付结果。
轮询缺陷:
- 2008年提出,2011年成为标准
- 最早是HTML5新增的协议,现在基本所有的语言都支持
- 作用:可以在浏览器和服务器之间建立一个全双工的通信通道(就是浏览器既可以往服务器发请求,服务器也可以往浏览器发请求,这就叫一个全双工的通信协议)
1. 浏览器发起HTTP请求,请求建立WebSocket连接
2. 服务器响应同意协议更改
3. 相互发送数据
在Spring里面已经帮我们实现了WebSocket的基本功能,它完成了HTTP协议升级为WebSocket协议的这个过程,封装了通信,以及完成了很多的通信细节的功能。
我们并不是要去实现WebSocket这个功能的后端开发,我们要做的就是在Spring给我们提供的实现了WebSocket功能的基础之上去完成一些业务功能的开发,这些业务的功能可以有两种方式来实现:
LomBok依赖可以让我们更方便的去打印日志,同时它还提供一些注解可以快速的给实体类生成Getter、Setter方法。
- package com.gch.java;
-
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
-
- import javax.websocket.OnClose;
- import javax.websocket.OnMessage;
- import javax.websocket.OnOpen;
- import javax.websocket.Session;
- import javax.websocket.server.ServerEndpoint;
- import java.io.IOException;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
-
-
- /**
- 监听WebSocket客户端地址/myWs谁来连接了WebSocket服务端
- */
- @ServerEndpoint("/myWs")
- @Component // 声明为一个Bean
- @Slf4j
- public class WsServerEndpoint {
- // 有多个客户端来连接,应该使用线程安全的CurrentHashMap
- public static Map<String,Session> sessionMap = new ConcurrentHashMap<>();
- // 当WebSocket客户端连接WebSocket服务端的时候,我们需要来声明一下我们的服务端去做哪些事情
- // 连接建立时执行的操作
- @OnOpen
- // 每一个WebSocket连接对于服务端来说都是一个session
- public void onOpen(Session session){
- sessionMap.put(session.getId(),session);
- log.info("websocket is open");
- }
- // 监听通信
- // 当WebSocket客户端浏览器给WebSocket服务器发消息的时候,我服务器做什么事情
- // 收到了客户端消息执行的操作
- @OnMessage
- public String onMessage(String text){
- log.info("收到了一条信息:" + text);
- return "已收到你的消息";
- }
- // 监听到连接关闭时执行的操作
- @OnClose
- public void onClose(Session session){
- sessionMap.remove(session.getId(),session);
- log.info("websocket is close");
- }
-
- // 每隔多少毫秒去执行一次定时任务给客户端发送xx
- @Scheduled(fixedRate = 2000)
- public void sendMsg() throws IOException {
- for(String key: sessionMap.keySet()){
- sessionMap.get(key).getBasicRemote().sendText("心跳");
- }
- }
-
- // 现在,Spring框架并不能扫描到我们的服务终端,我们还需要再加一个配置类
- // HTTP加上S之后它是一个更安全的传输
- }

- package com.gch.java;
-
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.socket.server.standard.ServerEndpointExporter;
-
- /**
- * 配置类
- * 注入Spring WebSocket框架里的一个对象叫做ServerEndpointExporter
- */
- @Configuration
- public class WebSocketConfig {
- @Bean
- public ServerEndpointExporter serverEndpointExporter(){
- return new ServerEndpointExporter();
- }
- }

- package com.gch;
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.scheduling.annotation.EnableScheduling;
-
- @EnableScheduling // 开启定时任务
- @SpringBootApplication
- public class WebsocketQuickstartApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(WebsocketQuickstartApplication.class, args);
- }
-
- }
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>ws client</title>
- </head>
- <body>
- </body>
-
- <script>
- let ws = new WebSocket("ws://localhost:8080/myWs")
- ws.onopen = function (){
- ws.send("hello")
- }
- ws.onmessage = function (message) {
- console.log(message.data)
- }
- </script>
- </html>

Spring框架已经在应用层面去帮我们定义了一些接口和抽象类,我们只要实现这些接口和抽象类,就能够完成一个目录比较清晰的WebSocket的服务器端,并且它里面有很多封装的功能我们可以直接使用。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。