WebFlux 004、WebFilter踩坑记录( 二 )

,就不会在出现上述异常 。
修改后部分代码如下:
// 半正确@Overridepublic Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {if (!enableGateway) {ServerHttpRequest request = exchange.getRequest();String token = Optional.ofNullable(request.getHeaders().getFirst(Constants.TOKEN)).orElse(“”);return getUser(token).flatMap(user -> {ServerHttpRequest mutateRequest = exchange.getRequest().mutate().header(UserUtils.MEMBER_ID, user.getMemId()).header(UserUtils.MOBILE, user.getMobile()).build();ServerWebExchange newexchange = exchange.mutate().request(mutateRequest).build();return chain.filter(newexchange);});}return chain.filter(exchange);}虽然现在不回在出现异常,但是去掉switchIfEmpty后,代码逻辑是不完整的,当获取不到User时,返回Mono.emtpy,那会直接结束流程,不在执行剩下的filter或其他逻辑 。真是连环坑,一坑接一坑 。所以对代码需要调整一番,调整后如下:
// 有点正确 但是不多@Overridepublic Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {if (!enableGateway) {ServerHttpRequest request = exchange.getRequest();String token = Optional.ofNullable(request.getHeaders().getFirst(Constants.TOKEN)).orElse(“”);return getUser(token).switchIfEmpty(Mono.error(() -> new BizException(ErrorCode.USER_IS_NULL_ERROR))).flatMap(user -> {ServerHttpRequest mutateRequest = exchange.getRequest().mutate().header(UserUtils.MEMBER_ID, user.getMemId()).header(UserUtils.MOBILE, user.getMobile()).build();ServerWebExchange newexchange = exchange.mutate().request(mutateRequest).build();return chain.filter(newexchange);}).onErrorResume(e -> chain.filter(exchange));}return chain.filter(exchange);}当获取用户为空后,抛出异常,然后在兜底,当异常的时候执行chain.filter(exchange)(好蠢的方式.. 但是解决问题了) 。
2.4 意外之喜各位看官,就在我写完上完上面的代码修改方案之后,读了一下修改完后的代码,突然发现问题出在哪了,所以连夜修改了代码方式 。现在我听我细细道来 。
2.4.1 问题点原因点:chain.filter(exchange)重复执行
switchIfEmpty(chain.filter(exchange))这个点本意是想用在当getUser 方法为空时,执行其它WebFilter的逻辑,从而不影响主流程 。
忽略了一点是:当chain.filter(newexchange)这个方法执行完后,返回的也是Mono<Void>,也是为空 。所以无论如何,代码最后的逻辑都会走到switchIfEmpty(chain.filter(exchange))
但是当getUser获取到用户后,会重复执行chain.filter(exchange),如下

  • return chain.filter(newexchange)
  • switchIfEmpty(chain.filter(exchange))
由于第一次执行完chain.filter(exchange),request、response都已经关闭,所以出现了xx COMPLETE,那看来的确符合逻辑 。
2.4.2 验证猜想这个验证方式还是挺简单的,那就是分别传入正常的TOKEN和错误的TOKEN 。
具体操作:.....(本人已完成)
结论:
当传入错误的token的时候,确实没有抛出异常,完美执行 。但是当传入正确的token,出现了熟悉的异常 。
2.4.3 代码调整知道问题的原因,那就好调整代码了 。修改后如下:
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {if (!enableGateway) {ServerHttpRequest request = exchange.getRequest();String token = Optional.ofNullable(request.getHeaders().getFirst(Constants.TOKEN)).orElse(request.getHeaders().getFirst("suuid"));return getUser(token).map(user -> {ServerHttpRequest mutateRequest = exchange.getRequest().mutate().header(UserUtils.MEMBER_ID, user.getMemId()).header(UserUtils.MOBILE, user.getMobile()).build();return exchange.mutate().request(mutateRequest).build();// 调整当getUser为空时,返回的内容}).switchIfEmpty(Mono.just(exchange)).flatMap(chain::filter);}return chain.filter(exchange);}

经验总结扩展阅读