【发布时间】:2021-02-26 12:41:27
【问题描述】:
我正在使用带有关系数据库的 Spring Webflux 开发一个反应式应用程序,存储库查询是通过服务中的线程池进行的。这是我的 findById 方法的代码。
@Override
public Mono<UserDTO> findById(Long id) {
return Mono.defer(() -> Mono.just(userRepository.findById(id))).flatMap(optional -> {
if (optional.isPresent()) {
return Mono.just(convertToDto(optional.get()));
}
return Mono.empty();
}).subscribeOn(Schedulers.boundedElastic());
}
当我集成一个 AOP 日志来跟踪应用层时出现问题:
@Around("within(@org.springframework.stereotype.Controller *) || within(@org.springframework.stereotype.Service *) || execution(public !void org.springframework.data.repository.Repository+.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
try {
Object result = joinPoint.proceed();
LOGGER.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint
.getSignature().getName(), result);
return result;
} catch (IllegalArgumentException e) {
LOGGER.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature()
.getDeclaringTypeName(),
joinPoint.getSignature().getName(), e);
throw e;
}
}
在此代码中,当结果是 Mono 或 Flux 时,会显示结果:MonoSubscribeOn:
2020-11-14 22:35:25.394 DEBUG 31132 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect : Exit: com.*.springboot.webflux.api.app.services.UserServiceImpl.findById() with result = MonoSubscribeOn
2020-11-14 22:35:25.396 DEBUG 31132 --- [ctor-http-nio-3] *.webflux.api.app.aop.LoggingAspect : Exit: com.*.springboot.webflux.api.app.web.controllers.UserController.get() with result = MonoDefaultIfEmpty
2020-11-14 22:35:25.399 DEBUG 31132 --- [oundedElastic-3] *.webflux.api.app.aop.LoggingAspect : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
Hibernate:
select
user0_.id as id1_0_0_,
user0_.birthdate as birthdat2_0_0_,
user0_.email as email3_0_0_,
user0_.name as name4_0_0_,
user0_.surname as surname5_0_0_
from
users user0_
where
user0_.id=?
2020-11-14 22:35:25.417 DEBUG 31132 --- [oundedElastic-3] *.webflux.api.app.aop.LoggingAspect : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:35:17.221)]
如果我更改我的代码以获得单声道或通量的值(在示例中只有单声道),对存储库的调用是重复的,我想这是因为必须在日志代码中完成订阅:
@Around("within(@org.springframework.stereotype.Controller *) || within(@org.springframework.stereotype.Service *) || execution(public !void org.springframework.data.repository.Repository+.*(..))")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
}
try {
Object result = joinPoint.proceed();
if (LOGGER.isDebugEnabled()) {
if (result instanceof Mono) {
((Mono<Object>)result).subscribe(monoResult -> {
LOGGER.debug("Exit Mono: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint
.getSignature().getName(), monoResult);
});
} else {
LOGGER.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(), joinPoint
.getSignature().getName(), result);
}
}
return result;
} catch (IllegalArgumentException e) {
LOGGER.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature()
.getDeclaringTypeName(),
joinPoint.getSignature().getName(), e);
throw e;
}
}
Log result:
2020-11-14 22:38:16.693 DEBUG 21424 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
2020-11-14 22:38:16.694 DEBUG 21424 --- [oundedElastic-4] *.webflux.api.app.aop.LoggingAspect : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
2020-11-14 22:38:16.699 DEBUG 21424 --- [oundedElastic-8] *.webflux.api.app.aop.LoggingAspect : Enter: org.springframework.data.repository.CrudRepository.findById() with argument[s] = [1]
Hibernate:
select
user0_.id as id1_0_0_,
user0_.birthdate as birthdat2_0_0_,
user0_.email as email3_0_0_,
user0_.name as name4_0_0_,
user0_.surname as surname5_0_0_
from
users user0_
where
user0_.id=?
Hibernate:
select
user0_.id as id1_0_0_,
user0_.birthdate as birthdat2_0_0_,
user0_.email as email3_0_0_,
user0_.name as name4_0_0_,
user0_.surname as surname5_0_0_
from
users user0_
where
user0_.id=?
Hibernate:
select
user0_.id as id1_0_0_,
user0_.birthdate as birthdat2_0_0_,
user0_.email as email3_0_0_,
user0_.name as name4_0_0_,
user0_.surname as surname5_0_0_
from
users user0_
where
user0_.id=?
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-8] *.webflux.api.app.aop.LoggingAspect : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)]
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-4] *.webflux.api.app.aop.LoggingAspect : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)]
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect : Exit: org.springframework.data.repository.CrudRepository.findById() with result = Optional[User(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)]
2020-11-14 22:38:16.713 DEBUG 21424 --- [oundedElastic-1] *.webflux.api.app.aop.LoggingAspect : Exit Mono: com.*.springboot.webflux.api.app.services.UserServiceImpl.findById() with result = UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379)
2020-11-14 22:38:16.714 DEBUG 21424 --- [oundedElastic-4] *.webflux.api.app.aop.LoggingAspect : Exit Mono: com.*.springboot.webflux.api.app.web.controllers.UserController.get() with result = <200 OK OK,UserDTO(id=1, name=John, surname=Doe, email=john@mail.com, birthdate=2020-11-14 22:37:20.379),[Content-Type:"application/json"]>
还有其他方法可以恢复 Flux 的价值吗?我不能使用 Mono.bock,因为它会锁定线程。
【问题讨论】:
-
那么你的问题解决了吗?你愿意写一个正确的答案吗?
-
@MartinTarjányi 我已经添加了我的最终解决方案
-
答案不属于问题。为了每个人的利益,请将其分解为正确的答案。您甚至可以接受自己的答案以结束问题。这就是您正确处理 SO 上的自我回答的方式。 ??????
标签: spring spring-webflux spring-aop reactive