首页 > 解决方案 > spring boot - 将正确的响应映射到请求,用于多异步调用

问题描述

我编写了一个 spring-boot 应用程序,它从用户那里接收一个名为 Calc 的对象,该对象包含两个参数,并返回一个包含复杂计算的答案(计算本身与问题无关)。因为系统可能很忙,所以每个对象都进入队列,队列上有一个按顺序传递的调度器,执行计算。

我的问题是如何将项目的计算结果返回到正确的请求。

我已经包含了我编写的代码:

控制器:

@RestController
public class CalcController {

    @Autowired
    private CalculateService calculateService;

    @RequestMapping("/")
    public int calculate(@RequestBody Calc calc) {
        return calculateService.calculate(calc);
    }
}

计算对象:

@Data
public class Calc {
    private int paramA;
    private int paramB;
}

计算服务:

@Service
public class CalculateService {
    private BlockingQueue<Calc> calcQueue;

    @PostConstruct
    private void init() {
        calcQueue = new LinkedBlockingDeque<>();
    }

    public int calculate(Calc calc) {
        calcQueue.add(calc);

        // TODO: Return calculation result.
        return 0;
    }

    @Scheduled(fixedRate = 2000)
    public void calculateQueue() throws InterruptedException {
        while (!calcQueue.isEmpty()) {
            Calc calc = calcQueue.take();
            int result = Calculator.calculate(calc);
            // TODO: Return calculation result to the right request.
        }
    }
}

谢谢

标签: javamultithreadingspring-boot

解决方案


您可以使用 Spring 的 @Async 功能

  1. 创建线程池
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

@EnableAsync
@Configuration
public class ThreadConfig {
    @Bean(name = "threadPoolTaskExecutor")
    public Executor threadPoolTaskExecutor() {
        return new ThreadPoolTaskExecutor();
    }
}
  1. 更新calculateService,你不需要在Queue中存储对象,它将由Spring的async工具处理
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;

@Service
public class CalculateService {
    @Async("threadPoolTaskExecutor")
    public CompletableFuture<Integer> calculate(Calc calc) {
        int result = Calculator.calculate(calc);
        return CompletableFuture.completedFuture(result);
    }
}
  1. 将控制器方法更新为
import com.example.service.CalculateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@RestController
public class CalcController {

    @Autowired
    private CalculateService calculateService;

    @RequestMapping("/")
    public int calculate(@RequestBody Calc calc) throws ExecutionException, InterruptedException {
        CompletableFuture<Integer> resultFut = calculateService.calculate(calc);
        // some other calls/logic
        return resultFut.get();
    }
}

如果您想按请求存储会话,请参阅SO 帖子


推荐阅读