背景
这里我们有一个需求:
当用户支付成功时,需要修改订单状态;短信通知用户;通知仓库发货
原始解决方法
你首先想到的肯定是这样
1 2 3 4 5 6 7
| public void paySuccess(String orderId) { if (StringUtils.isNotBlank(orderId)) { //1.修改订单状态 //2.发送短信通知用户 //3.通知仓库发货 } }
|
在支付成功的方法里面调用修改订单的方法,调用短信通知用户的方法,调用仓库发货的方法。完事了,你觉得很简单嘛。
但是,产品经理说,我要改需求了,不止要短信通知,我还要微信通知。这个还是简单。
1 2 3 4 5 6
| if (StringUtils.isNotBlank(orderId)) { //1.修改订单状态 //2.发送短信通知用户 //3.通知仓库发货 //4.微信通知 }
|
过了一天产品经理又来加需求了,我还要可以QQ通知,这也不难。
1 2 3 4 5 6 7
| if (StringUtils.isNotBlank(orderId)) { //1.修改订单状态 //2.发送短信通知用户 //3.通知仓库发货 //4.微信通知 //5.QQ通知 }
|
过了一个月,产品经理又来了:“给我加个功能,我要支付成功后还可以发放优惠券,还要发放积分…”
需求没完没了,但这时你已经忘了支付成功的代码写在哪里了。
终于,你找到了,开始编写。突然,你意识到,不对呀,这个方法越来越臃肿了。而且每次还要来修改这个支付成功的方法,万一修改错误怎么办。
你还意识到一个问题,这些功能都是同步的,万一我调用微信通知的功能失败,难道就不能QQ通知,不能发放优惠券了么?还要全部都回滚。太不合常理了。
你苦思冥想,了解到了一个事件监听机制的方法,可以异步解耦,不正适合这个场景么。说干就干,代码重构走起。
事件监听解决方法
这里我就不说什么是事件监听机制了,概念百度一大把,我将从实际的例子说起,让你彻底理解这个机制是做什么的,什么时候用它。
我们先来定义一个支付事件类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| /** * Description: 支付事件 * * @author Lvshen * @version 1.0 * @date: 2020-8-28 13:56 * @since JDK 1.8 */ public class PayEvent extends ApplicationEvent { //订单id private String orderId;
public String getOrderId() { return orderId; }
public void setOrderId(String orderId) { this.orderId = orderId; }
public PayEvent(Object source,String orderId) { super(source); this.orderId = orderId; } }
|
支付服务类这么写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
@Component public class PayService {
@Autowired public ApplicationEventPublisher applicationEventPublisher;
public void paySuccess(String orderId) { if (StringUtils.isNotBlank(orderId)) { applicationEventPublisher.publishEvent(new PayEvent(this, orderId)); } } }
|
这里支付成功后,会发布事件。这里的需求是支付后需要短信通知用户,通知订单修改状态,通知仓库准备发货。我们分别创建相关类来接收发布的事件。
OrderService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| /** * Description:订单服务 * * @author Lvshen * @version 1.0 * @date: 2020-8-28 14:10 * @since JDK 1.8 */ @Component public class OrderService {
@EventListener public void updateOrderStatus(PayEvent payEvent) { String orderId = payEvent.getOrderId(); //修改订单状态 System.out.println(String.format("支付成功,修改订单【%s】状态为已支付!!!",orderId)); } }
|
当订单服务监听到支付服务发过来的数据,开始修改数据。
SmsService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| /** * Description:短信服务 * * @author Lvshen * @version 1.0 * @date: 2020-8-28 14:16 * @since JDK 1.8 */ @Component public class SmsService {
@EventListener public void sendMessage(PayEvent payEvent) { String orderId = payEvent.getOrderId(); //短信功能 System.out.println(String.format("支付成功,发送【%s】短信",orderId)); } }
|
短信服务监听支付事件,当支付成功,监听到事件,并将支付成功的消息发送给用户。
WarehouseService
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| /** * Description:仓库服务 * * @author Lvshen * @version 1.0 * @date: 2020-8-28 14:21 * @since JDK 1.8 */ @Component public class WarehouseService { @EventListener public void sendProduct(PayEvent payEvent) { String orderId = payEvent.getOrderId(); //发货功能 System.out.println(String.format("支付成功,准备发货,订单【%s】",orderId)); } }
|
同样,当仓库监听到支付成功的事件,开始准备发货。