SpringBoot-事件驱动开发-3

一、简介

        在上一节中,学了各种回调监听器,其中有一种监听器叫做ApplicationListener,它是用来监听发送事件的,在本节中可以利用它来做事件驱动开发。

1.事件驱动开发-理解

(1)事件驱动开发是一种编程范式,它主要面向事件的处理,而不是传统的基于顺序的编程。 事件驱动编程的核心思想是通过事件来驱动程序的执行,而不是基于顺序执行的代码块。

(2)场景(理解)

  • 用户登录后,我们基于用户登录的信息,会调用账户服务、优惠服务、系统服务....,一般的代码应该是这样去写的,注入各种各样的服务,如果后续还有操作,继续往下增加对应的业务,但设计模式中我们应该新增开发,对修改要关闭,利用事件以后,我们只需要发送一个事件,其余服务监听这个事件做对应的操作即可

  • 事件驱动开发(相关服务监听事件做对应操作)

二、事件驱动开发-实践

1.ApplicationListener回顾

(1)当自定义了该监听器后会进行事件的推送

  • 发送请求

  • 我们访问对应的地址时,springboot中ApplicationListener会推送对应的事件,那么可以利用它去自定义事件,就能够做到事件驱动的开发

2.驱动开发过程

(1)Controller

package com.yang.controller;


import com.yang.entity.User;
import com.yang.event.EventPublisher;
import com.yang.event.LoginEvent;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class LoginController {
    @Resource
    private EventPublisher eventPublisher;

    /**
     * 登录
     */
    @GetMapping("/login")
    public String login(@RequestParam("username") String username,
                        @RequestParam("password") String password){
        //1、创建事件信息
        LoginEvent loginEvent = new LoginEvent(new User(username, password));
        //2、发送事件
        eventPublisher.sendEvent(loginEvent);
        return "successful!";
    }
}

(2)Event(组装事件信息,发送事件)

  • LoginEvent 
package com.yang.event;

import com.yang.entity.User;
import org.springframework.context.ApplicationEvent;

/**
 * 登录事件组装
 * 要发送的事件都必须继承ApplicationEvent
 */
public class LoginEvent extends ApplicationEvent {

    public LoginEvent(User source) {
        super(source);
    }
}
  •  EventPublisher:需要继承ApplicationEventPublisherAware(拿到springboot给我们注入的发送事件组件),组件ApplicationEventPublisher发送的事件是广播,所有服务想收该事件都能够收到,收到的顺序是按字母排序的,也可以用@Order注解指定顺序
package com.yang.event;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;

@Service
public class EventPublisher implements ApplicationEventPublisherAware {

    /**
     * 底层发送事件用的组件,SpringBoot会通过ApplicationEventPublisherAware接口自动注入给我们
     *
     */
    private ApplicationEventPublisher publisher;

    /**
     * 发送事件
     * @param event
     */
    public void sendEvent(ApplicationEvent event) {
        // 调用底层API发事件
        publisher.publishEvent(event);
    }

    /**
     * 会被自动调用,把真正发事件的底层组件给我们注入进来
     * @param applicationEventPublisher event publisher to be used by this object
     */
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.publisher = applicationEventPublisher;
    }
}

 (3)entity

package com.yang.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private String name;
    private String passwd;

}

(4)Service

  • AccountService:可以实现ApplicationListener<LoginEvent>
package com.yang.service;

import com.yang.entity.User;
import com.yang.event.LoginEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Service;

/**
 * ApplicationListener<LoginEvent>表示只接收LoginEvent类型的事件
 * 如果是填入ApplicationListener<ApplicationEvent>表示接收所有事件
 */
@Service
public class AccountService implements ApplicationListener<LoginEvent> {

    public void addAccountScore(String username){
        System.out.println(username + " 加1积分");
    }

    @Override
    public void onApplicationEvent(LoginEvent event) {
        System.out.println("AccountService 收到事件 =====>" + event);
        User source = (User) event.getSource();
        addAccountScore(source.getName());
    }
}
  • CouponService:也可以使用注解@EventListener
package com.yang.service;

import com.yang.entity.User;
import com.yang.event.LoginEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

@Service
public class CouponService {

    public void sendCoupon(String username) {
        System.out.println("给用户" + username + "发送优惠券");
    }

    @EventListener
    public void receiveEvent(LoginEvent event){
        System.out.println("CouponService 收到事件 =====>" + event);
        User source = (User) event.getSource();
        sendCoupon(source.getName());
    }
}

(5)运行结果

2024-12-21T23:21:24.809+08:00  INFO 32756 --- [nio-8080-exec-3] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-12-21T23:21:24.809+08:00  INFO 32756 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-12-21T23:21:24.809+08:00  INFO 32756 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : Completed initialization in 0 ms
========>事件推送:com.yang.event.LoginEvent[source=User(name=xiaoming, passwd=123456)]
AccountService 收到事件 =====>com.yang.event.LoginEvent[source=User(name=xiaoming, passwd=123456)]
xiaoming 加1积分
CouponService 收到事件 =====>com.yang.event.LoginEvent[source=User(name=xiaoming, passwd=123456)]
给用户xiaoming发送优惠券
========>事件推送:ServletRequestHandledEvent: url=[/login]; client=[0:0:0:0:0:0:0:1]; method=[GET]; servlet=[dispatcherServlet]; session=[null]; user=[null]; time=[24ms]; status=[OK]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值