返回顶部
首页 > 资讯 > 后端开发 > Python >Spring 异步接口返回结果的四种方式
  • 840
分享到

Spring 异步接口返回结果的四种方式

2024-04-02 19:04:59 840人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录1. 需求2. 解决方案2.1 @Async2.2 TaskExecutor2.3 Future2.4 @EventListener3. 总结1. 需求 开发中我们经常遇到异步接

1. 需求

开发中我们经常遇到异步接口需要执行一些耗时的操作,并且接口要有返回结果。

使用场景:用户绑定邮箱、手机号,将邮箱、手机号保存入库后发送邮件或短信通知
接口要求:数据入库后给前台返回成功通知,后台异步执行发邮件、短信通知操作

一般的话在企业中会借用消息队列来实现发送,业务量大的话有一个统一消费、管理的地方。但有时项目中没有引用MQ相关组件,这时为了实现一个功能去引用、维护一个消息组件有点大材小用,下面介绍几种不引用消息队列情况下的解决方式

定义线程池:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;

@EnableAsync
@Configuration
public class CommonConfig {
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

        // 设置核心线程数
        executor.setCorePoolSize(50);
        // 设置最大线程数
        executor.setMaxPoolSize(200);
        // 设置队列容量
        executor.setQueueCapacity(200);
        // 设置线程活跃时间(秒)
        executor.seTKEepAliveSeconds(800);
        // 设置默认线程名称
        executor.setThreadNamePrefix("task-");
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        return executor;
    }
}

2. 解决方案

2.1 @Async

定义异步任务,如发送邮件、短信等

@Service
public class ExampleServiceImpl implements ExampleService {
    @Async("taskExecutor")
    @Override
    public void sendMail(String email) {
        try {
            Thread.sleep(3000);
            System.out.println("异步任务执行完成, " + email + " 当前线程:" + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

Controller

@RequestMapping(value = "/api")
@RestController
public class ExampleController {
    @Resource
    private ExampleService exampleService;

    @RequestMapping(value = "/bind",method = RequestMethod.GET)
    public String bind(@RequestParam("email") String email) {
        long startTime = System.currentTimeMillis();
        try {
            // 绑定邮箱....业务
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //模拟异步任务(发邮件通知、短信等)
        exampleService.sendMail(email);

        long endTime = System.currentTimeMillis();
        System.out.println("方法执行完成返回,耗时:" + (endTime - startTime));
        return "ok";
    }
}

运行结果:

2.2 TaskExecutor

@RequestMapping(value = "/api")
@RestController
public class ExampleController {
    @Resource
    private ExampleService exampleService;
    @Resource
    private TaskExecutor taskExecutor;

    @RequestMapping(value = "/bind", method = RequestMethod.GET)
    public String bind(@RequestParam("email") String email) {
        long startTime = System.currentTimeMillis();
        try {
            // 绑定邮箱....业务
            Thread.sleep(2000);

            // 将发送邮件交给线程池去执行
            taskExecutor.execute(() -> {
                exampleService.sendMail(email);
            });
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("方法执行完成返回,耗时:" + (endTime - startTime));
        return "ok";
    }
}

运行结果:

2.3 Future

首先去掉Service方法中的@Async("taskExecutor"),此时执行就会变成同步,总计需要5s才能完成接口返回。这次我们使用jdk1.8中的CompletableFuture来实现异步任务

@RequestMapping(value = "/api")
@RestController
public class ExampleController {
    @Resource
    private ExampleService exampleService;
    @Resource
    private TaskExecutor taskExecutor;

    @RequestMapping(value = "/bind", method = RequestMethod.GET)
    public String bind(@RequestParam("email") String email) {
        long startTime = System.currentTimeMillis();
        try {
            // 绑定邮箱....业务
            Thread.sleep(2000);

            // 将发送邮件交给异步任务Future,需要记录返回值用supplyAsync
            CompletableFuture.runAsync(() -> {
                exampleService.sendMail(email);
            }, taskExecutor);

        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("方法执行完成返回,耗时:" + (endTime - startTime));
        return "ok";
    }
}

运行结果:

2.4 @EventListener

Spring为我们提供的一个事件监听、订阅的实现,内部实现原理是观察者设计模式;为的就是业务系统逻辑的解耦,提高可扩展性以及可维护性。事件发布者并不需要考虑谁去监听,监听具体的实现内容是什么,发布者的工作只是为了发布事件而已。

2.4.1 定义event事件模型

public class NoticeEvent extends ApplicationEvent {
    private String email;
    private String phone;
    public NoticeEvent(Object source, String email, String phone) {
        super(source);
        this.email = email;
        this.phone = phone;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
}

2.4.2 事件监听

@Component
public class ComplaintEventListener {

    
    @Async
    @EventListener(value = NoticeEvent.class)
//    @Order(1) 指定事件执行顺序
    public void sendEmail(NoticeEvent noticeEvent) {
        //发邮件
        try {
            Thread.sleep(3000);
            System.out.println("发送邮件任务执行完成, " + noticeEvent.getEmail() + " 当前线程:" + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Async
    @EventListener(value = NoticeEvent.class)
//    @Order(2) 指定事件执行顺序
    public void sendMsg(NoticeEvent noticeEvent) {
        //发短信
        try {
            Thread.sleep(3000);
            System.out.println("发送短信步任务执行完成, " + noticeEvent.getPhone() + " 当前线程:" + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

2.4.5 事件发布

@RequestMapping(value = "/api")
@RestController
public class ExampleController {
    
    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @RequestMapping(value = "/bind", method = RequestMethod.GET)
    public String bind(@RequestParam("email") String email) {
        long startTime = System.currentTimeMillis();
        try {
            // 绑定邮箱....业务
            Thread.sleep(2000);

            // 发布事件,这里偷个懒手机号写死
            applicationEventPublisher.publishEvent(new NoticeEvent(this, email, "13211112222"));
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("方法执行完成返回,耗时:" + (endTime - startTime));
        return "ok";
    }
}

运行结果:

3. 总结

通过@Async、子线程、Future异步任务、Spring自带ApplicationEvent事件监听都可以完成以上描述的需求。

到此这篇关于Spring 异步接口返回结果的四种方式的文章就介绍到这了,更多相关Spring 异步接口内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Spring 异步接口返回结果的四种方式

本文链接: https://lsjlt.com/news/166215.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Spring 异步接口返回结果的四种方式
    目录1. 需求2. 解决方案2.1 @Async2.2 TaskExecutor2.3 Future2.4 @EventListener3. 总结1. 需求 开发中我们经常遇到异步接...
    99+
    2024-04-02
  • java异步接口怎么返回结果
    在Java中,异步接口可以通过回调函数、Future和CompletionStage等方式返回结果。1. 回调函数:定义一个接口,其...
    99+
    2023-08-09
    java
  • Spring接口支持返回多种格式的方法
    本篇内容介绍了“Spring接口支持返回多种格式的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成! 1...
    99+
    2024-04-02
  • springboot异步返回结果的方法是什么
    Spring Boot提供了多种异步返回结果的方法,以下是其中几种常用的方法:1. 使用`async`注解:在Controller的...
    99+
    2023-08-09
    springboot
  • Spring Boot异步线程间数据传递的四种方式
    目录Spring Boot 自定义线程池实现异步开发1. 手动设置2. 线程池设置TaskDecorator3. InheritableThreadLocal4. Transmitt...
    99+
    2023-01-06
    Spring Boot异步线程数据传递 Spring Boot异步线程
  • java对接webservice接口的四种方式
    这两天一直在做外系统对接,对方的接口是webservice的形式,调用起来有些蛋疼,于是在这里记录一下我尝试过的调用WebService的三种方式。 方式一:以HttpURLConnection的方式调用 String url ="http...
    99+
    2023-10-21
    java python 开发语言
  • Android异步更新UI的四种方式
    大家都知道由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中更新UI,大致有4种方式,下面分别使用四种方式来更新一个TextView。 1.使用Hand...
    99+
    2022-06-06
    Android
  • Java调用第三方http接口的方式总结(四种)
    在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适。很多项目都会封装规定好本身项目的接口规范,所以大多数需要去调用对方提供的接口或第三方接口(短信、天气等) ①通过JDK网络类Java.net.HttpURLConn...
    99+
    2023-08-16
    Java Http 接口
  • SpringBoot接口返回结果封装方法实例详解
    rest接口会返回各种各样的数据,如果对接口的格式不加约束,很容易造成混乱。 在实际项目中,一般会把结果放在一个封装类中,封装类中包含http状态值,状态消息,以及实际的数据。这里主...
    99+
    2024-04-02
  • SpringBoot异步处理的四种实现方式
    本篇文章我们以SpringBoot中异步的使用(包括:异步调用和异步方法两个维度)来进行讲解。 异步请求与同步请求 我们先通过一张图来区分一下异步请求和同步请求的区别: 在上图...
    99+
    2024-04-02
  • Spring Boot统一接口返回及全局异常处理的方法
    这篇文章主要讲解了“Spring Boot统一接口返回及全局异常处理的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Spring Boot统一接口返回及全局异常处理的...
    99+
    2023-06-30
  • Python获取协程返回值的四种方式详解
    目录介绍源码依次执行结果介绍 获取协程返回值的四种方式: 1、通过ensure_future获取,本质是future对象中的result方 2、使用loop自带的create_tas...
    99+
    2024-04-02
  • C#调用接口的四种方式介绍
    在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用,所以首先需要通过调用登录接口来保存cookie...
    99+
    2024-04-02
  • spring接口通过配置支持返回多种格式(xml,json,html,excel)
    1. 简介本文主要给大家介绍使用SpringMVC的后端服务如何通过配置来支持多种返回值类型(xml,json,html,excel)这里的代码使用的是springboot,下载地址:https://github.com/xiagn825/...
    99+
    2023-05-30
    spring 接口 返回格式
  • API接口统一格式返回的方法
    本篇内容介绍了“API接口统一格式返回的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!接口交互前端和后端进行交互,前端按照约定请求URL...
    99+
    2023-06-27
  • vue中返回结果是promise的处理方式
    目录返回结果是promise的处理对promise的一些理解1.promise是一种异步解决方案2.async await返回结果是promise的处理 调用element-ui中提...
    99+
    2024-04-02
  • Golang 函数对返回结果的处理方式
    go 函数可以通过 return 语句返回结果,返回结果类型由函数签名中的最后一个参数列表决定。处理返回结果的方法包括:无返回结果:无须处理。单一返回值:使用赋值运算符分配给变量。多个返...
    99+
    2024-05-23
    golang 函数处理
  • Java 异步实现的几种方式小结
    Java 异步实现的几种方式 1. jdk1.8之前的Future jdk并发包里的Future代表了未来的某个结果,当我们向线程池中提交任务的时候会返回该对象,可以通过future...
    99+
    2024-04-02
  • C# 执行CMD命令并接收返回结果的操作方式
    最近工作的时候发现软件里面通过查询ARP表查询某一IP对应的ARP条目的时,概率性出现查询到的ARP条目为空,一开始怀疑Ping通但是没有学习到ARP, 后来想想这是不可能的,最后经...
    99+
    2024-04-02
  • Java实现线程同步的四种方式总结
    目录什么是线程同步线程同步的几种方式1.使用synchronized关键字2.使用ReentrantLock3.使用原子变量实现线程同步4.ThreadLocal实现线程同步什么是线...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作