Day72(9)-F:\硕士阶段\Java\课程资料\1、黑马程序员Java项目《苍穹外卖》企业级开发实战\sky-take-out
苍穹外卖
SpringTask
cron
package com.sky.task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* 自定义定时任务类
*/
@Component
@Slf4j
public class MyTask {
/**
* 定时任务,每隔五秒触发一次
*/
@Scheduled(cron = "0/5 * * * * ? ")
public void executeTask(){
log.info("任务开始执行:{}",new Date());
}
}
订单定时处理
技术栈:
- 轮询
1.轮询
package com.sky.task;
import com.sky.entity.Orders;
import com.sky.mapper.OrderMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
/**
* 定时任务类,定时处理订单状态
*/
@Component
@Slf4j
public class OrderTask {
@Autowired
private OrderMapper orderMapper;
/**
* 处理超时订单的方法
*/
//@Scheduled(cron = "0/5 * * * * ? ")
@Scheduled(cron = "0 * * * * *")
public void processTimeoutOrder(){
log.info("定时处理超时订单:{}", LocalDateTime.now());
LocalDateTime time = LocalDateTime.now().plusMinutes(-15);
//select * from orders where status = ? and order_time < (当前时间-15分钟)
List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time);
if (ordersList!=null&&ordersList.size()>0){
for (Orders orders : ordersList) {
orders.setStatus(Orders.CANCELLED);
orders.setCancelReason("订单超时,自动取消");
orders.setCancelTime(LocalDateTime.now());
orderMapper.update(orders);
}
}
}
/**
* 处理一直处于派送中状态的订单
*/
@Scheduled(cron = "0 0 1 * * ?")
//@Scheduled(cron = "0/10 * * * * ? ")
public void processDeliveryOrder(){
log.info("定时处理一直处于派送中的订单:{}",LocalDateTime.now());
LocalDateTime time = LocalDateTime.now().plusMinutes(-60);
List<Orders> ordersList = orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, time);
if (ordersList!=null&&ordersList.size()>0){
for (Orders orders : ordersList) {
orders.setStatus(Orders.COMPLETED);
orderMapper.update(orders);
}
}
}
}
WebSocket
http是短连接
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
package com.sky.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* WebSocket配置类,用于注册WebSocket的Bean
*/
@Configuration
public class WebSocketConfiguration {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
server类相当于controller
package com.sky.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.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* WebSocket服务
*/
@Component
@ServerEndpoint("/ws/{sid}")
public class WebSocketServer {
//存放会话对象
private static Map<String, Session> sessionMap = new HashMap();
/**
* 连接建立成功调用的方法
*/
@OnOpen
public void onOpen(Session session, @PathParam("sid") String sid) {
System.out.println("客户端:" + sid + "建立连接");
sessionMap.put(sid, session);
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message, @PathParam("sid") String sid) {
System.out.println("收到来自客户端:" + sid + "的信息:" + message);
}
/**
* 连接关闭调用的方法
*
* @param sid
*/
@OnClose
public void onClose(@PathParam("sid") String sid) {
System.out.println("连接断开:" + sid);
sessionMap.remove(sid);
}
/**
* 群发
*
* @param message
*/
public void sendToAllClient(String message) {
Collection<Session> sessions = sessionMap.values();
for (Session session : sessions) {
try {
//服务器向客户端发送消息
session.getBasicRemote().sendText(message);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package com.sky.task;
import com.sky.websocket.WebSocketServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Component
public class WebSocketTask {
@Autowired
private WebSocketServer webSocketServer;
/**
* 通过WebSocket每隔5秒向客户端发送消息
*/
@Scheduled(cron = "0/5 * * * * ?")
public void sendMessageToClient() {
webSocketServer.sendToAllClient("这是来自服务端的消息:" + DateTimeFormatter.ofPattern("HH:mm:ss").format(LocalDateTime.now()));
}
}
来单提醒
技术栈
- nginx反向代理配置
- 通过webSocket在支付成功后推送过来,在impl中完成这个操作
1.nginx反向代理配置
在nginx的配置类中有
# 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";
}
upstream webservers{
server 127.0.0.1:8080 weight=90 ;
#server 127.0.0.1:8088 weight=10 ;
}
2.通过webSocket在支付成功后推送过来,在impl中完成这个操作
如果是微信能支付应该是在微信后台回调后端之后发送这个信息
/**
* 支付成功,修改订单状态
*
* @param outTradeNo
*/
public void paySuccess(String outTradeNo) {
// 根据订单号查询订单
Orders ordersDB = orderMapper.getByNumber(outTradeNo);
// 根据订单id更新订单的状态、支付方式、支付状态、结账时间
Orders orders = Orders.builder()
.id(ordersDB.getId())
.status(Orders.TO_BE_CONFIRMED)
.payStatus(Orders.PAID)
.checkoutTime(LocalDateTime.now())
.build();
orderMapper.update(orders);
//通过WebSocket向客户端浏览器推送信息 type orderId Content
Map<Object, Object> map = new HashMap<>();
map.put("type",1);//1.表示来单提醒 2.表示客户催单
map.put("orderId",ordersDB.getId());
map.put("content","订单号:"+outTradeNo);
String json = JSON.toJSONString(map);
webSocketServer.sendToAllClient(json);
}
但是我们不能,个体账户无法支付
所以改为在payment就发信息(38-48行)
/**
* 订单支付
*
* @param ordersPaymentDTO
* @return
*/
public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
// 当前登录用户id
Long userId = BaseContext.getCurrentId();
User user = userMapper.getById(userId);
//调用微信支付接口,生成预支付交易单
// JSONObject jsonObject = weChatPayUtil.pay(
// ordersPaymentDTO.getOrderNumber(), //商户订单号
// new BigDecimal(0.01), //支付金额,单位 元
// "苍穹外卖订单", //商品描述
// user.getOpenid() //微信用户的openid
// );
//
// if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
// throw new OrderBusinessException("该订单已支付");
// }
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", "ORDERPAID");
OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
//vo.setPackageStr(jsonObject.getString("package"));
//为替代微信支付成功后的数据库订单状态更新,多定义一个方法进行修改
Integer OrderPaidStatus = Orders.PAID; //支付状态,已支付
Integer OrderStatus = Orders.TO_BE_CONFIRMED; //订单状态,待接单
//发现没有将支付时间 check_out属性赋值,所以在这里更新
LocalDateTime check_out_time = LocalDateTime.now();
orderMapper.updateStatus(OrderStatus, OrderPaidStatus, check_out_time, Long.valueOf(ordersPaymentDTO.getOrderNumber()));
// 根据订单号查询当前用户的订单
Orders ordersDB = orderMapper.getByNumber(ordersPaymentDTO.getOrderNumber());
//通过WebSocket向客户端浏览器推送信息 type orderId Content
Map<Object, Object> map = new HashMap<>();
map.put("type",1);//1.表示来单提醒 2.表示客户催单
map.put("orderId",ordersDB.getId());
map.put("content","订单号:"+ordersPaymentDTO.getOrderNumber());
String json = JSON.toJSONString(map);
webSocketServer.sendToAllClient(json);
return vo;
}
客户催单
/**
* 客户催单
* @param id
* @return
*/
@ApiOperation("客户催单")
@GetMapping("/reminder/{id}")
public Result reminder(@PathVariable Long id){
log.info("客户催单:{}",id);
orderService.reminder(id);
return Result.success();
}
/**
* 客户催单
* @param id
*/
@Override
public void reminder(Long id) {
Orders orders = orderMapper.getById(id);
if (orders==null||orders.getStatus()!=Orders.TO_BE_CONFIRMED){
throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
}
HashMap<Object, Object> map = new HashMap<>();
map.put("type",2);//1.表示来单提醒 2.表示客户催单
map.put("orderId",id);
map.put("content",orders.getNumber());
String json = JSON.toJSONString(map);
webSocketServer.sendToAllClient(json);
}

浙公网安备 33010602011771号