测试小站: 处理网 回收帮 培训网 富贵论坛 老富贵论坛

Spring Boot 事件和监听

  1、自定义事件和监听

  1.1、定义事件

  1 package com.cjs.boot.event;

  2

  3 import lombok.Data;

  4 import org.springframework.context.ApplicationEvent;

  5

  6 @Data

  7 public class BlackListEvent extends ApplicationEvent {

  8

  9 private String address;

  10

  11 public BlackListEvent(Object source, String address) {

  12 super(source);

  13 this.address=address;

  14 }

  15 }

  1.2、定义监听

  1 package com.cjs.boot.event;

  2

  3 import org.springframework.context.ApplicationListener;

  4 import org.springframework.context.event.EventListener;

  5 import org.springframework.stereotypeponent;

  6

  7 8 public class BlackListListener implements ApplicationListener {

  9

  10 @Override

  11 public void onApplicationEvent(BlackListEvent event) {

  12 System.out.println("监听到BlackListEvent事件: " + event.getAddress());

  13 try {

  14 Thread.sleep(2000);

  15 } catch (InterruptedException e) {

  16 e.printStackTrace();

  17 }

  18 }

  19 }

  1.3、注册监听

  1 package com.cjs.boot;

  2

  3 import com.cjs.boot.event.BlackListListener;

  4 import org.springframework.boot.SpringApplication;

  5 import org.springframework.boot.autoconfigure.SpringBootApplication;

  6 import org.springframework.boot.web.server.ErrorPage;

  7 import org.springframework.boot.web.server.ErrorPageRegistrar;

  8 import org.springframework.boot.web.server.ErrorPageRegistry;

  9 import org.springframework.cache.annotation.EnableCaching;

  10 import org.springframework.context.annotation.Bean;

  11 import org.springframework.http.HttpStatus;

  12 import org.springframework.scheduling.annotation.EnableAsync;

  13

  14 @SpringBootApplication

  15 public class CjsSpringbootExampleApplication {

  16

  17 public static void main(String[] args) {

  18

  19 SpringApplication springApplication=new SpringApplication(CjsSpringbootExampleApplication.class);

  20 springApplication.addListeners(new BlackListListener());

  21 springApplication(args);

  22

  23 }

  1.4、发布事件

  1 package com.cjs.boot.controller;

  2

  3 import com.cjs.boot.event.BlackListEvent;

  4 import org.springframework.beans.factory.annotation.Autowired;

  5 import org.springframework.context.ApplicationContext;

  6 import org.springframework.context.ApplicationEventPublisher;

  7 import org.springframework.web.bind.annotation.GetMapping;

  8 import org.springframework.web.bind.annotation.RequestMapping;

  9 import org.springframework.web.bind.annotation.RestController;

  10

  11 @RestController

  12 @RequestMapping("/activity")

  13 public class ActivityController {

  14

  15 // @Autowired

  16 // private ApplicationEventPublisher publisher;

  17

  18 @Autowired

  19 private ApplicationContext publisher;

  20

  21 @GetMapping("/sayHello.json")

  22 public void sayHello() {

  23

  24 /**

  25 * You may register as many event listeners as you wish, but note that by default event listeners receive events synchronously.

  26 * This means the publishEvent() method blocks until all listeners have finished processing the event.

  27 */

  28

  29 BlackListEvent event=new BlackListEvent(this, "abc@126");

  30 publisherlishEvent(event);

  31 System.out.println("事件发布成功");

  32 }

  33

  34 }

  2、基于注解的事件监听

  package com.cjs.boot.event;

  import org.springframework.context.event.EventListener;

  import org.springframework.stereotypeponent;

  @Component

  public class BlackListListener {

  @EventListener

  public void processBlackListEvent(BlackListEvent event) {

  System.out.println(123);

  }

  }

  ---

  package com.cjs.boot;

  import org.springframework.boot.SpringApplication;

  import org.springframework.boot.autoconfigure.SpringBootApplication;

  @SpringBootApplication

  public class CjsSpringbootExampleApplication {

  public static void main(String[] args) {

  SpringApplication(CjsSpringbootExampleApplication.class, args);

  }

  }

  3、异步监听

  1 @EventListener

  2 @Async

  3 public void processBlackListEvent(BlackListEvent event) {

  4 // BlackListEvent is processed in a separate thread

  5 }

  4、应用

  6 import lombok.extern.slf4j.Slf4j;

  7 import org.springframework.beans.factory.annotation.Autowired;

  8 import org.springframework.context.event.EventListener;

  9 import org.springframework.scheduling.annotation.Async;

  10 import org.springframework.stereotypeponent;

  11

  12 import java.util.ArrayList;

  13 import java.util.List;

  14 import java.util.concurrent.ExecutionException;

  15 import java.util.concurrent.Future;

  16 import java.util.concurrent.atomic.AtomicInteger;

  17

  18 /**

  19 * 批量送券

  20 */

  21 @Slf4j

  22 @Component

  23 public class BatchSendCouponListener {

  24

  25 @Autowired

  26 private CouponPresentLogService couponPresentLogService;

  27

  28 @Async

  29 @EventListener

  30 public void processBatchSendCouponEvent(BatchSendCouponEvent batchSendCouponEvent) {

  31 Long cpId=batchSendCouponEvent.getCouponPresentId();

  32 log("收到BatchSendCouponEvent, cpId={}", cpId);

  33 List list=couponPresentLogService.selectByPid(cpId);

  34

  35 handle(cpId, list, 0);

  36 }

  37

  38 private void handle(Long cpId, List list, int times) {

  39 if (times >=2) {

  40 log("超过重试次数退出, cpId: {}, 剩余: {}", cpId, list.size());

  41 return;

  42 }

  43

  44 List<Future> futureList=new ArrayList<>();

  45

  46 for (CouponPresentLogEntity entity : list) {

  47 futureList.add(couponPresentLogService.present(entity));

  48 }

  49

  50 AtomicInteger count=new AtomicInteger(0);

  51 // 收集失败的

  52 List failList=new ArrayList<>();

  53 for (Future future : futureList) {

  54 try {

  55 CouponPresentLogEntity couponPresentLogEntity=future.get();

  56 if (couponPresentLogEntity.getStatus() !=PresentStatusEnum.SUCCESS.getType().intValue()) {

  57 failList.add(couponPresentLogEntity);

  58 }

  59 count.getAndIncrement();

  60 if (count.intValue() >=list.size()) {

  61 List failPresentLogList=couponPresentLogService.selectFailLogByPid(cpId);

  62 if (null !=failPresentLogList && failPresentLogList.size() > 0) {

  63 times++;

  64 log("第{}次重试, CPID: {}, 总计: {}, 失败: {}", times, cpId, list.size(), failPresentLogList.size());

  65 handle(cpId, failPresentLogList, times);

  66 }

  67 }

  68 } catch (InterruptedException e) {

  69 log.error(e.getMessage(), e);

  70 } catch (ExecutionException e) {

  71 log.error(e.getMessage(), e);

  72 }

  73 }

  74 }

  75

  76 }

  1 import lombok.extern.slf4j.Slf4j;

  2 import org.springframework.beans.factory.annotation.Autowired;

  3 import org.springframework.scheduling.annotation.Async;

  4 import org.springframework.scheduling.annotation.AsyncResult;

  5 import org.springframework.stereotype.Service;

  6

  7 import javax.annotation.Resource;

  8 import java.util.concurrent.*;

  9

  10 @Service

  11 @Slf4j

  12 public class CouponPresentLogServiceImpl implements CouponPresentLogService {

  13

  14 @Autowired

  15 private CouponPresentLogDao couponPresentLogDao;

  16 @Resource

  17 private CouponSendRpcService couponSendRpcService;

  18

  19 @Async("myThreadPoolTaskExecutor")

  20 @Override

  21 public Future present(CouponPresentLogEntity entity) {

  22 try {

  23 CouponBaseResponse rst=couponSendRpcService.send(entity.getUserId(), entity.getCouponBatchKey(), "1", entity.getVendorId());

  24 if (null !=rst && rst.isSuccess()) {

  25 entity.setStatus(PresentStatusEnum.SUCCESS.getType());

  26 entity.setFailureReason(PresentStatusEnum.SUCCESS.getName());

  27 }else {

  28 String reason=(null==rst) ? "响应异常" : rst.getMsg();

  29 entity.setFailureReason(reason);

  30 entity.setStatus(PresentStatusEnum.FAILURE.getType());

  31 }

  32 }catch (Exception ex) {

  33 log.error(ex.getMessage(), ex);

  34 entity.setFailureReason(ex.getMessage());

  35 entity.setStatus(PresentStatusEnum.FAILURE.getType());

  36 }

  37 couponPresentLogDao.update(entity);

  38

  39 return new AsyncResult(entity);

  40 }

  41

  42 }

  5、统计异步任务执行的进度

  利用Future获取执行结果,比如上面的例子中,由于不是直接提交的任务,所以用AsyncResult来返回结果

  上面的例子中,一个大任务,然后下面有许多子任务。在主任务中,统计各子任务的执行情况,是成功还是失败,然后统计成功多少,失败多少

  也可以这样写:

  @Autowired

  ThreadPoolTaskExecutor taskExecutor;

  Future

  @Override

  public Object call() throws Exception {

  return null;

  }

  });

posted @ 2021-12-11 20:52  linjingyg  阅读(208)  评论(0)    收藏  举报