如何在Spring事务提交后进行异步操作

2025-05-13 18:11:05
推荐回答(2个)
回答(1):

实现方案
使用TransactionSynchronizationManager在事务提交之后操作
public void insert(TechBook techBook){
bookMapper.insert(techBook);
// send after tx commit but is async
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
System.out.println("send email after transaction commit...");
}
}
);
ThreadLocalRandom random = ThreadLocalRandom.current();
if(random.nextInt() % 2 ==0){
throw new RuntimeException("test email transaction");
}
System.out.println("service end");
}

该方法就可以实现在事务提交之后进行操作
操作异步化
使用mq或线程池来进行异步,比如使用线程池:
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
public void insert(TechBook techBook){
bookMapper.insert(techBook);

// send after tx commit but is async
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
@Override
public void afterCommit() {
executorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("send email after transaction commit...");
try {
Thread.sleep(10*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("complete send email after transaction commit...");
}
});
}
}
);

// async work but tx not work, execute even when tx is rollback
// asyncService.executeAfterTxComplete();

ThreadLocalRandom random = ThreadLocalRandom.current();
if(random.nextInt() % 2 ==0){
throw new RuntimeException("test email transaction");
}
System.out.println("service end");
}

回答(2):

import java.util.HashSet;
import java.util.Set;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.SessionTrackingMode;
import javax.servlet.annotation.WebListener;

@WebListener
public class SetSessionTrackingModeListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent sce) {
Set modes = new HashSet();
modes.add(SessionTrackingMode.URL); // thats the default behaviour!
modes.add(SessionTrackingMode.COOKIE);
sce.getServletContext().setSessionTrackingModes(modes);
}

public void contextDestroyed(ServletContextEvent sce) {
}

}