我们有多个在循环内调用的依赖 API,我们需要将每个 API 响应保存在一个审核表中。现在,我们面临一个问题,比如如果第一个 API 抛出一些异常(400/500...),我们需要在审计表中至少存储审计数据,但由于 @Transactional,它正在滚动审计表数据而且我们不想回滚这些数据。
请提出需要的建议。
我们尝试过,但没有成功
@Transactional(propagation = Propagation.NEVER)
,
@Transactional(propagation = Propagation.NOT_SUPPORTED)
对于 NOT_SUPPORTED,将停止继续进行。
@Transactional
public void apiImplementation() {
auditService.addDataInAuditTable("123","...");
boolean isLastPage = true;
int currentPage = 0;
do {
ResponseEntity<AbcModel> response = restApiService
apiCallToGetAbcDetails(100, currentPage++);
if (response != null && response.getStatusCode() == HttpStatus.OK) {
AbcModel abcModel = response.getBody();
if (abcModel != null) {
isLastPage = abcModel.isLastPage();
abcModel.getData.forEach(this::secondApiImplementation);
}
}
} while (!isLastPage);
}
private void secondApiImplementation(AbcModel abcModel) {
here we're saving data and calling the second Api... and also save data in auditlog for second api
}
这是
spring-aop
的典型用例。
如果您只有一种方法来处理所有方法的错误,本质上您将使用
@Auditable
定义您的审核方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable{}
@Transactional
@Auditable
public void apiImplementation(){
// Stuff
}
然后在你的
Aspect
@Aspect
@Component
public class AuditAspect {
@Around("@annotation(auditable)")
public void audit(ProceedingJoinPoint joinPoint) throws Throwable {
try{
// You can audit before if you would like
joinPoint.proceed();
} finally {
//Do your thing here (call another service/repository or private methods). You will audit regardless of the method execution.
}
}
}
如果您还想审核 API 的响应,您还可以捕获
proceed()
的结果。
如果你想检索 api 方法的运行时参数,你可以使用 这个答案
请注意,
spring-aop
仅适用于代理方法。它不会拦截任何private secondApiImplementation()
。