首页 > 解决方案 > spring restservice 异步日志记录功能

问题描述

我在春季编写了运行良好的休息服务。

现在,我需要在向用户返回响应之前添加执行一些数据库事务。

此数据库事务独立于检索到的响应。

例如,

@PostMapping("login")
    public TransactionResponse loginAuthentication(@Valid @RequestBody LoginRequestBody loginRequest) {
        TransactionResponse transactionResponse = new TransactionResponse();
        try {
            transactionResponse = loginService.validateUser(loginRequest);

            //independent transaction needs to be executed in a separate thread
            loginSerice.addLoginLog(transactionResponse);

            //return below response without waiting to compelete above log transaction
            return transactionResponse; 
        }
        catch (Exception e) {
            return CommonUtils.setErrorResponse(transactionResponse, e);
        }

    }

我在 spring mvc link中阅读了异步控制器。尽管控制器在单独的线程中执行相应的功能,但我不想等待数据库事务完成。从服务层得到响应后,应立即转发给用户。

有什么建议么 !!

春季版本是 4.3

标签: springasynchronouscallable

解决方案


我发布了这个答案以帮助有相同要求的开发人员(在单独的线程中执行 void 函数)。

由于我在多线程/异步环境中没有经验,我想通过使用 spring 异步方法来保持简单。

所以,首先我创建了线程池

@Configuration
@EnableAsync
public class ThreadConfig {

    @Bean
    public TaskExecutor threadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(4);
        executor.setMaxPoolSize(4);
        executor.setThreadNamePrefix("WEBAPP");
        executor.initialize();

        return executor;
    }
}

然后我创建了一个服务,它将在单独的线程中执行我的代码。

@Async
@Service
@Transactional
public class LoggingService {

    public void logintransaction() throws Exception{ 
        System.out.println("start login loggin");

        Thread.sleep(5000);

        System.out.println("exit");
    }

}

最后,我在控制器上调用了上述服务。如我所见Total Time Taken,首先打印,然后打印“开始登录登录”。这意味着我的新方法在新线程中执行。

@Autowired
    private LoggingService loggingService;


    @PostMapping("login")
    public TransactionResponse loginAuthentication(@Valid @RequestBody LoginRequestBody loginRequest) {
        long startTime = System.currentTimeMillis();
        TransactionResponse transactionResponse = new TransactionResponse();
        try {
            transactionResponse = loginService.validateUser(loginRequest);

            //independent transaction needs to be executed in a separate thread
            //loginSerice.addLoginLog(transactionResponse);
            loggingService.logintransaction();

            //return below response without waiting to compelete above log transaction

            System.err.println("Total Time Taken=>"+(System.currentTimeMillis() - startTime));
            return transactionResponse; 
        }
        catch (Exception e) {
            return CommonUtils.setErrorResponse(transactionResponse, e);
        }

    }

谢谢


推荐阅读