学习复盘和总结项目亮点。
扩展:该功能能应用在,各种服务类项目中。(例如:酒店、洗脚城等系ERP系中提醒类服务)
用户下单并且支付成功后,需要第一时间通知外卖商家。通知的形式有如下两种:
语音播报
弹出提示框
设计实现思路:
通过WebSocket实现管理端页面和服务端保持长连接状态(建立长连接)
当客户支付后,调用WebSocket的相关API实现服务端向客户端推送消息
客户端浏览器解析服务端推送的消息,判断是来单提醒还是客户催单,进行相应的消息提示和语音播报
约定服务端发送给客户端浏览器的数据格式为JSON,字段包括:type,orderId,content
type 为消息类型,1为来单提醒 2为客户催单
orderId 为订单id
content 为消息内容
1、建立长连接
nginx.conf配置
upstream webservers{
server 192.168.0.1:8080 weight=90 ;
}
# WebSocket
location /ws/ {
? ? ? ? ? proxy_pass ? http://webservers/ws/;
proxy_http_version 1.1;
proxy_read_timeout 3600s;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "$connection_upgrade";
? ? ? }
(WebSocketServer对象在上一篇文章已经定义。)
在OrderServiceImpl中注入WebSocketServer对象,修改paySuccess方法,加入如下代码:
@Autowired
? ?private WebSocketServer webSocketServer;
/**
? ? * 支付成功,修改订单状态
? ? *
? ? * @param outTradeNo
? ? */
? ?public void paySuccess(String outTradeNo) {
? ? ? ?// 当前登录用户id
? ? ? ?Long userId = BaseContext.getCurrentId();
?
? ? ? ?// 根据订单号查询当前用户的订单
? ? ? ?Orders ordersDB = orderMapper.getByNumberAndUserId(outTradeNo, userId);
?
? ? ? ?// 根据订单id更新订单的状态、支付方式、支付状态、结账时间
? ? ? ?Orders orders = Orders.builder()
? ? ? ? ? ? ? .id(ordersDB.getId())
? ? ? ? ? ? ? .status(Orders.TO_BE_CONFIRMED)
? ? ? ? ? ? ? .payStatus(Orders.PAID)
? ? ? ? ? ? ? .checkoutTime(LocalDateTime.now())
? ? ? ? ? ? ? .build();
?
? ? ? ?orderMapper.update(orders);
//
? ? ? ?Map map = new HashMap();
? ? ? ?map.put("type", 1);//消息类型,1表示来单提醒
? ? ? ?map.put("orderId", orders.getId());
? ? ? ?map.put("content", "订单号:" + outTradeNo);
?
? ? ? ?//通过WebSocket实现来单提醒,向客户端浏览器推送消息
? ? ? ?webSocketServer.sendToAllClient(JSON.toJSONString(map));
? ? ? ?//转成json格式数据并还回
? }
可以通过如下方式进行测试:
查看浏览器调试工具数据交互过程
前后端联调
1). 登录管理端后台
登录成功后,浏览器与服务器建立长连接
查看控制台日志
2). 小程序端下单支付
修改回调地址,利用内网穿透获取域名
下单支付? ?(添加商品并扫码下单)
3). 查看来单提醒
支付成功后,后台收到来单提醒,并有语音播报(语音播报需要前端实现/后端负责数据还回)
用户在小程序中点击催单按钮后,需要第一时间通知外卖商家。通知的形式有如下两种:
语音播报
弹出提示框
设计思路:
通过WebSocket实现管理端页面和服务端保持长连接状态
当用户点击催单按钮后(接口),调用WebSocket的相关API实现服务端向客户端推送消息
客户端浏览器解析服务端推送的消息,判断是来单提醒还是客户催单,进行相应的消息提示和语音播报 约定服务端发送给客户端浏览器的数据格式为JSON,字段包括:type,orderId,content
type 为消息类型,1为来单提醒 2为客户催单
orderId 为订单id
content 为消息内容
当用户点击催单按钮时,向服务端发送请求。
接口设计(催单):
根据用户催单的接口定义,在user/OrderController中创建催单方法:
/**
? ? * 用户催单
? ? *
? ? * @param id
? ? * @return
? ? */
? ?@GetMapping("/reminder/{id}")
? ?@ApiOperation("用户催单")
? ?public Result reminder(@PathVariable("id") Long id) {
? ? ? ?orderService.reminder(id);
? ? ? ?return Result.success();
? }
在OrderService接口中声明reminder方法:
/**
? ? * 用户催单
? ? * @param id
? ? */
? ?void reminder(Long id);
在OrderServiceImpl中实现reminder方法:
/**
? ? * 用户催单
? ? *
? ? * @param id
? ? */
? ?public void reminder(Long id) {
? ? ? ?// 查询订单是否存在
? ? ? ?Orders orders = orderMapper.getById(id);
? ? ? ?if (orders == null) {
? ? ? ? ? ?throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
? ? ? }
?
? ? ? ?//基于WebSocket实现催单
? ? ? ?Map map = new HashMap();
? ? ? ?map.put("type", 2);//2代表用户催单
? ? ? ?map.put("orderId", id);
? ? ? ?map.put("content", "订单号:" + orders.getNumber());
? ? ? ?webSocketServer.sendToAllClient(JSON.toJSONString(map));
? }
5.2.4 Mapper层
在OrderMapper中添加getById:
/**
? ? * 根据id查询订单
? ? * @param id
? ? */
? ?@Select("select * from orders where id=#{id}")
? ?Orders getById(Long id);
可以通过如下方式进行测试:
查看浏览器调试工具数据交互过程
前后端联调
1). 登录管理端后台
登录成功后,浏览器与服务器建立长连接
查看控制台日志
2). 用户进行催单
用户可在订单列表或者订单详情,进行催单
3). 查看催单提醒
既有催单弹窗,同时语音播报