controller
@GetMapping("/aspect")
public Flux<String> testAspect(@RequestParam String name) {
return Flux.just("tom", "jerry", "jucifer", "kaige")
.map(s -> {
if ("kaige".equalsIgnoreCase(s)) {
throw new RuntimeException("kaige is very handsome");
}
return s;
});
}
aspect
@Aspect
@Component
@Slf4j
public class FluxAspect {
@Pointcut("execution(* com.paranoia.webfluxreactive.router..*(..))")
public void logPointCut() {
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
String className = point.getTarget().getClass().getName();
String methodName = signature.getName();
Object[] args = point.getArgs();
log.info("class :" + className +
" -> method : -> " + methodName +
" -> args : -> " + Arrays.toString(args));
try {
return point.proceed();
} catch (Throwable throwable) {
//经验证,webflux 异常不会在这里被捕获
throwable.printStackTrace();
log.error("something wrong : " + throwable.getLocalizedMessage());
return throwable.getLocalizedMessage();
}
}
}
请求:
http://localhost:8080/platform/aspect?name=hi
结果:
字符串‘kaige’并没有返回,说明异常抛出没问题。但是切面并没有像mvc那样将异常捕捉到。
重新尝试:
添加一个异常类型的切点
@AfterThrowing(value = "logPointCut()", throwing = "throwable")
public void tryException(Throwable throwable) {
System.out.println("throwable = " + throwable);
}
异常还是没有捕捉到,控制台打印如下:
[ctor-http-nio-3] c.p.webfluxreactive.aspect.FluxAspect : class :com.paranoia.webfluxreactive.router.SysPlatformController -> method : -> testAspect -> args : -> [hi]
[ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : Unhandled failure: kaige is very handsome, response already set (status=null)
[ctor-http-nio-3] o.s.h.s.r.ReactorHttpHandlerAdapter : Handling completed with error: kaige is very handsome
目测是ReactorHttpHandlerAdapter 这个类将异常处理掉了。
再次尝试:ControllerAdvice
@ControllerAdvice
@Slf4j
public class GloableExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public String gloabExceptionHandler(Exception e){
log.error("操作失败",e);
return "操作失败";
}
}
结果:
[ctor-http-nio-3] c.p.webfluxreactive.aspect.FluxAspect : class :com.paranoia.webfluxreactive.router.SysPlatformController -> method : -> testAspect -> args : -> [hi]
[ctor-http-nio-3] c.p.w.exception.GloableExceptionHandler : 操作失败
java.lang.RuntimeException: kaige is very handsome
at com.paranoia.webfluxreactive.router.SysPlatformController.lambda$testAspect$0(SysPlatformController.java:54) ~[classes/:na]
at ...
[ctor-http-nio-3] o.s.w.s.adapter.HttpWebHandlerAdapter : Unhandled failure: null, response already set (status=null)
[ctor-http-nio-3] o.s.h.s.r.ReactorHttpHandlerAdapter : Handling completed with error: null
发现handler提前于Adapter前将异常捕捉处理掉,Adapter打印的是Handling completed with error: null,它并没有拿到异常信息。
总结:
- webflux和webmvc切面的逻辑上有区别。flux可以和mvc一样拿到请求信息,但是拿不到异常信息。
- ExceptionHandler一如既往可以正常拿到异常信息。
fixme:
- ReactorHttpHandlerAdapter 在异常流程中的担任什么角色?
- 异常上下文如何贯穿起来?