# 监听器解释

  1. 监听一个对象的某个事件,对象的某个事件发生的时候触发监听器代码.

# 业务场景

  1. 一对多调用场景,比如当一个账号注册成功后,要给发送短信,要初始化这个人的积分为0,要刷新缓存,还要做很多其他的事情,我们想不到,那我们怎么办呢?难道是想到了在继续改业务代码吗?有没有一种松耦合的方式解决此问题呢? 当然有,我们今天说的监听器就是为了解决此问题的.

# fhs监听器的几个名词

  1. namespace: 代表被监听对象的别名,比如user
  2. event: 事件, user 可能有多个事件,比如注册成功,比如修改密码成功
  3. listener: 监听器,监听器中配置了我要监听谁的什么事件,要触发什么动作

# 使用FHS监听器

  1. 首先确定被监听者的事件名和namespace,在事件发生的时候调用所有的监听器.
  1. //注入监听器注册中心
  2. @Autowired
  3. protected DistributedListenerRegister distributedListenerRegister;
  4. // 发送通知
  5. Map<String,Object> extMap = new HashMap<>();
  6. extMap.put(CommonConstant.USER_ID,changePricePO.getUpdateUser());
  7. try{
  8. distributedListenerRegister.callListener("user", "updatePassword", changePricePO,extMap);
  9. }catch (Exception e){
  10. LOGGER.error(JsonUtils.bean2json(changePricePO) + "自动提交失败",e);
  11. }

2.实现一个普通监听器

  1. @Component
  2. public class UserUpdatePasswordHelloListener implements DistributedListener {
  3. @Override
  4. public Set<String> namespace() {
  5. Set<String> namespaceSet = new HashSet<>();
  6. //采购订单
  7. namespaceSet.add("user");
  8. return namespaceSet;
  9. }
  10. @Override
  11. public String eventType() {
  12. return "updatePassword";
  13. }
  14. @Override
  15. public Map<String, Object> onMessage(Map<String, Object> param) {
  16. System.out.println('我知道了,用户改密码了');
  17. return null;
  18. }
  19. }

3.实现一个分布式监听器(使用springcloud) A 定义一个监听器接口,让用户注册服务的 application 依赖此接口.

  1. FeignClient(name = "jiuzhou-module-bill-web", primary = false)
  2. public interface RegistingBaseReverseAuditListenerRpcService extends DistributedListener {
  3. /**
  4. * 目标业务namespace
  5. *
  6. * @return
  7. */
  8. @Override
  9. default Set<String> namespace() {
  10. Set<String> namespaceSet = new HashSet<>();
  11. //采购订单
  12. namespaceSet.add("buyTaskOrder");
  13. return namespaceSet;
  14. }
  15. /**
  16. * 事件类型
  17. *
  18. * @return 事件类型
  19. */
  20. @Override
  21. default String eventType() {
  22. return CommonConstant.LISTENER_TYPE_REVERSE_AUDIT;
  23. }
  24. /***
  25. * 采购订单反审核的时候触发的方法
  26. * @param param 参数
  27. * @return 如果返回结果包含errorMsg 代表有关联数据
  28. */
  29. @Override
  30. default Map<String, Object> onMessage(Map<String, Object> param) {
  31. return this.buyTaskOrderReverseAuditCheck(param);
  32. }
  33. /**
  34. * 采购订单反审核
  35. *
  36. * @param param 参数
  37. * @return 反审核结果
  38. */
  39. @PostMapping("/rpc/com.e6yun.project.jiuzhou.module.check.service.CheckBillRegistedBaseService/buyTaskOrderReverseAuditCheck")
  40. Map<String, Object> buyTaskOrderReverseAuditCheck(@RequestBody Map<String, Object> param);
  41. /**
  42. * 这里返回2 指的是我比其他的listener后执行,优先执行合同本模块的listener然后执行我
  43. * 不然那些本模块的报错的话,我无法回滚
  44. *
  45. * @return
  46. */
  47. @Override
  48. default int getOrder() {
  49. return 2;
  50. }
  51. @Override
  52. default Class<? extends DistributedListener> getRpcInterfaceClass() {
  53. return RegistingBaseReverseAuditListenerRpcService.class;
  54. }
  55. @Override
  56. default boolean isRpc() {
  57. return true;
  58. }
  59. }

B 写他的实现类 此处省略,记得一定要 让对应的service 或者控制器 implement 此接口.

C 监听器注册中心在调用监听器的时候会优先找直接实现类来调用,如果找不到才会找feign代理实现.