Java Spring接口如何先返回响应再异步执行Steam充值业务?
Java中实现先返回响应再执行异步充值的方案
方案1:使用Spring自带@Async注解(最适配当前Spring Web场景)
操作步骤:
- 第一步:在Spring Boot启动类上添加
@EnableAsync注解,开启全局异步方法支持 - 第二步:在
SteamRechargeService类的rechargeSteamAccount方法上添加@Async注解,标记该方法为异步执行方法 - 第三步:调整Controller代码,将充值调用放在return语句之前即可,异步方法会自动提交到独立线程执行,不会阻塞主线程返回响应
改造后代码示例:
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<String> steamRecharge(@RequestBody RequestDTO request) throws Exception { // 同步执行余额校验,校验不通过会直接抛出异常返回错误 SteamRechargeService.checkIfClientHasEnoughMoneyOnAccount(request); // 异步执行充值操作,不会阻塞后续返回逻辑 SteamRechargeService.rechargeSteamAccount(request); // 直接返回响应(注意HttpStatus.ACCEPTED对应的状态码是202,你提到的406是NOT_ACCEPTABLE,建议核对需求状态码) return new ResponseEntity<>("Client has enough money", HttpStatus.ACCEPTED); }
注意:标注
@Async的方法必须是Spring容器管理的Bean的public方法,且不能和调用方在同一个类中,否则异步注解不生效。
方案2:手动创建线程池提交异步任务(更灵活可控)
如果不想依赖Spring的异步注解,可以自己定义全局线程池,手动提交异步任务:
// 先定义全局线程池,禁止每次请求创建新线程 private static final ExecutorService STEAM_RECHARGE_POOL = new ThreadPoolExecutor( 2, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(1000) ); @PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<String> steamRecharge(@RequestBody RequestDTO request) throws Exception { SteamRechargeService.checkIfClientHasEnoughMoneyOnAccount(request); // 手动提交异步任务 STEAM_RECHARGE_POOL.submit(() -> { try { SteamRechargeService.rechargeSteamAccount(request); } catch (Exception e) { // 异步任务的异常必须自行捕获处理,不会抛到Controller层 log.error("Steam充值失败,请求参数:{}", request, e); // 可在此处添加重试、告警逻辑 } }); return new ResponseEntity<>("Client has enough money", HttpStatus.ACCEPTED); }
额外注意事项
- 异步方法的异常不要向外抛出,需要内部捕获处理,避免影响主线程的响应返回
- 如果充值操作是强可靠需求,建议配合本地事件表、消息队列中间件实现,避免服务突然重启导致异步任务丢失
- 需求中提到的406状态码对应
HttpStatus.NOT_ACCEPTABLE,而接受异步处理的标准状态码是202HttpStatus.ACCEPTED,建议核对需求状态码的正确性
内容的提问来源于stack exchange,提问作者Rafael Picolo
相关产品推荐
相关产品推荐

