1. 应用场景
(1)浏览器打开的支付页面需要知道订单的支付状态
当用户扫码后,微信首先知道订单已经支付完成,微信可以通过下单时提交的回调接口,通知商户该订单的支付状态
商户需要实现一个接口用于接受微信的通知
在这个接口中,需要根据微信传来的订单编号,寻找到打开的支付页面的浏览器,并主动通知该浏览器订单支付成功了。
(2)投票结果展示页面,需要每隔3秒钟自动显示最新的投票结果
2. Websocket原理
(1)浏览器与后端服务器建立长连接,除非某一方主动关闭连接,否则该连接一致存在。
(2)该长连接是双向的,即允许浏览器主动给服务器发消息,也允许服务器主动给浏览器发消息(推送)。
3. Springboot实现Websocket
(1)POM文件中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
(2)WebSocket配置类
package com.qf.fmall.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 向IOC容器中添加ServerEndpointExporter类型的bean
* 作用:可以识别到我们编写websocket类上的@serverEndpoing 注解
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter endpointExporter(){
return new ServerEndpointExporter();
}
}
(3)WebSocket后端接口
package com.qf.fmall.websocket;
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.Arrays;
import java.util.Date;
import java.util.List;
@Component
@ServerEndpoint("/test")
public class MyWebSocketServer {
/**
* 当某个浏览器跟我们的服务器建立连接时,需要做的事情,写在这个方法里
*
* @param session 这个对象就是浏览器与服务器建立好的websocket长连接对象
* @throws IOException
*/
@OnOpen
public void onOpen(Session session) throws IOException, InterruptedException {
System.out.println("服务器端接收到了连接请求......");
//发送消息给浏览器
session.getBasicRemote().sendText("hello from server " + new Date().toLocaleString());
String line1 = "告白气球";
String line2 = "塞纳河畔左岸的咖啡";
String line3 = "我手一杯,品尝你的美";
String line4 = "留下唇印的嘴";
List<String> list = Arrays.asList(line1, line2, line3, line4);
for (String line : list) {
Thread.sleep(1000);
session.getBasicRemote().sendText(line);
}
}
/**
* 当浏览器发送消息给服务器时,需要做的事情,写在这个方法里
*
* @param session 这个对象就是浏览器与服务器建立好的websocket长连接对象
* @param msg 浏览器发送的消息的内容
*/
@OnMessage
public void onMessage(Session session, String msg) throws IOException {
System.out.println("接收到浏览器发送的消息内容为:" + msg);
//给浏览器发送一个消息
String serverMsg = "来自服务器端的响应:" + msg;
session.getBasicRemote().sendText(serverMsg);
}
/**
* 当浏览器关闭连接时,要做的事情写在这个方法里
*
* @param session
* @throws IOException
*/
@OnClose
public void onClose(Session session) throws IOException {
System.out.println("浏览器断开连接,断开的session对象为:" + session.getId());
session.close();
}
}
(4) 在线测试websocket接口
http://www.websocket-test.com/
4.websocket实现订单管理的微信支付的回调方法
在微信支付成功以后,微信发送一个请求给后端,告诉后端我完成支付了,后端收到这个请求以后会,修改数据库,然后把这个成功标志,通过websocket发送给前端,前端收到这个信息,判断为成功,然后修改页面html显示成功!!!
(1)配置类和上面一样,这里只写实现
package com.qf.fmall.websocket;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
@Component
@ServerEndpoint("/order/{orderid}")
public class OrderWebSocketServer {
public static HashMap<String,Session> sessionMap= new HashMap<>();
public static void pushMsg(String orderId, String msg) throws IOException {
Session session = sessionMap.get(orderId);
session.getBasicRemote().sendText(msg);
}
@OnOpen
public void onOpen(@PathParam("orderid") String orderid, Session session){
System.out.println("接收到浏览器的连接请求,orderid="+orderid);
//如何保存与该浏览器建立的session对象呢?
sessionMap.put(orderid,session);
}
@OnClose
public void onCloss(@PathParam("orderid") String orderid, Session session) throws IOException {
sessionMap.remove(orderid);
session.close();
}
}
(2)在OrderController里写一个回调接口
@GetMapping("/test/{orderid}")
public ResultVo testWebSocket(@PathVariable("orderid") String orderid) throws IOException {
//给该orderid打开的浏览器页面,主动推送一个消息
OrderWebSocketServer.pushMsg(orderid,"1");
return ResultVo.vo(FmallConstants.SUCCESS_CODE,FmallConstants.SUCCESS_MSG,"OK");
}
展示一下静态方法
/**
* 发送成功回调函数给前端
* @param orderId 订单编号
* @param msg 成功的信息
* @throws IOException
*/
public static void pushMsg(String orderId, String msg) throws IOException {
//修改数据库
Session session = sessionMap.get(orderId);
session.getBasicRemote().sendText(msg);
}
5.前端怎么发送websocket请求
//前端发送websocket连接请求
var webSocketUrl = "ws://127.0.0.1:8080/webSocket/订单编号";
var websocket = new WebSocket( webSocketUrl );
//只要后端通过websocket向此连接发消息就会触发onmessage事件
websocket.onmessage = function(event){
var msg = event.data;
if(msg=="1"){
$("#div1").html("<label style='font-size:20px; color:green'>订单支付完成!</label>");
}
}
websocket.onmessage = function(event)
这行代码是为WebSocket对象的 onmessage
事件设置一个事件处理程序。 当WebSocket连接从服务器接收到消息时,将触发 onmessage
事件。通过为 websocket.onmessage
赋予一个函数,您定义了在接收到消息时应采取的操作。 在提供的代码片段中, (event)
是当接收到消息时将执行的事件处理程序。您可以通过 event.data
在此函数中访问接收到的消息,并根据接收到的消息执行任何所需的操作或处理。 例如,您可以更新用户界面、显示接收到的消息,或者基于接收到的消息内容触发其他函数。
要通过WebSocket从前端向服务器发送消息,您需要建立WebSocket连接,然后使用 `send()` 方法将消息发送到服务器。以下是使用JavaScript实现的示例:
// 建立WebSocket连接
const socket = new WebSocket('ws://your-server-url');
// 连接打开时的事件监听器
socket.addEventListener('open', function (event) {
// 向服务器发送消息
socket.send('你好,服务器!');
});
// 来自服务器的消息的事件监听器
socket.addEventListener('message', function (event) {
// 处理从服务器接收到的消息
console.log('来自服务器的消息:', event.data);
});
在这个示例中,通过将服务器URL传递给构造函数创建了一个新的WebSocket对象。一旦连接打开,您可以使用 `send()` 方法向服务器发送消息。此外,您可以使用 `message` 事件监听器监听来自服务器的消息,并根据需要进行处理。
请确保将 `'ws://your-server-url'` 替换为实际的WebSocket服务器URL,以便连接到您希望连接的WebSocket服务器。
var websocket = new WebSocket( webSocketUrl );//连接服务器
socket.send('你好,服务器');//向服务器发送消息
socket.close('关闭服务器连接')//关闭与服务器的连接
socket.onmessage = function(event){
var msg = event.data;
if(msg=="1"){
$("#div1").html("<label style='font-size:20px; color:green'>订单支付完成!</label>");
}
}//服务器向前端发送消息的时候,触发的监听事件。