onErrorResume() 不会被调用
onErrorResume() won't get called
我是 spring webflux 和 reactor 的新手 我想在发生某些特定异常时有一个回退机制,并且根据我的研究 onErrorResume 方法可以做到这一点,但它不会被调用,我得到 500内部服务器错误而不是我的后备触发并防止此错误。
注意:我使用 spring webflux,这意味着它对 reactor 项目的正常行为进行了一些更改
public Mono<Date> getExpirationDateFromToken(String token) {
return getAllClaimsFromToken(token)
.onErrorResume(ExpiredJwtException.class, e -> Mono.just(e.getClaims()))
.map(Claims::getExpiration);
}
public Mono<Claims> getAllClaimsFromToken(String token) {
return Mono.just(Jwts.parserBuilder()
.setSigningKey(Base64.getEncoder().encodeToString(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody());
}
这是堆栈跟踪
io.jsonwebtoken.ExpiredJwtException: JWT expired at 2020-03-22T08:17:15Z. Current time: 2020-03-22T08:50:56Z, a difference of 2021835 milliseconds. Allowed clock skew: 0 milliseconds.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:439) ~[jjwt-impl-0.11.0.jar:0.11.0]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Handler ir.siavash.customerservice.security.controller.AuthController#refreshToken(Mono) [DispatcherHandler]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP POST "/auth/refreshToken" [ExceptionHandlingWebHandler]
Stack trace:
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:439) ~[jjwt-impl-0.11.0.jar:0.11.0]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:541) ~[jjwt-impl-0.11.0.jar:0.11.0]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:601) ~[jjwt-impl-0.11.0.jar:0.11.0]
at io.jsonwebtoken.impl.ImmutableJwtParser.parseClaimsJws(ImmutableJwtParser.java:173) ~[jjwt-impl-0.11.0.jar:0.11.0]
at ir.siavash.customerservice.security.JWTUtil.getAllClaimsFromToken(JWTUtil.java:42) ~[classes/:na]
好的,再一看,就清楚了。这是一个常见的错误。响应式组件可能很难学习,但您离解决方案不远了。
Mono.just 将 预先计算的 值作为参数。因此,您的 getAllClaimsFromToken 将仅在执行所有提供给 just 的代码后创建一个 Mono。这意味着您的错误发生在任何反应组件可用于错误管理(组装时间)之前。
您可以改为使用 Mono#fromCallable 让 Reactor 按需计算 Jwt 令牌,或者仅使用初始字符串创建 Mono,然后使用您的函数进行映射。
让我们看看第二个解决方案:
public Mono<Date> getExpirationDateFromToken(String token) {
return Mono.just(token)
.map(this::getAllClaimsFromToken)
.onErrorResume(ExpiredJwtException.class, e -> Mono.just(e.getClaims()))
.map(Claims::getExpiration);
}
public Claims getAllClaimsFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(Base64.getEncoder().encodeToString(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody();
}
我是 spring webflux 和 reactor 的新手 我想在发生某些特定异常时有一个回退机制,并且根据我的研究 onErrorResume 方法可以做到这一点,但它不会被调用,我得到 500内部服务器错误而不是我的后备触发并防止此错误。
注意:我使用 spring webflux,这意味着它对 reactor 项目的正常行为进行了一些更改
public Mono<Date> getExpirationDateFromToken(String token) {
return getAllClaimsFromToken(token)
.onErrorResume(ExpiredJwtException.class, e -> Mono.just(e.getClaims()))
.map(Claims::getExpiration);
}
public Mono<Claims> getAllClaimsFromToken(String token) {
return Mono.just(Jwts.parserBuilder()
.setSigningKey(Base64.getEncoder().encodeToString(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody());
}
这是堆栈跟踪
io.jsonwebtoken.ExpiredJwtException: JWT expired at 2020-03-22T08:17:15Z. Current time: 2020-03-22T08:50:56Z, a difference of 2021835 milliseconds. Allowed clock skew: 0 milliseconds.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:439) ~[jjwt-impl-0.11.0.jar:0.11.0]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Handler ir.siavash.customerservice.security.controller.AuthController#refreshToken(Mono) [DispatcherHandler]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP POST "/auth/refreshToken" [ExceptionHandlingWebHandler]
Stack trace:
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:439) ~[jjwt-impl-0.11.0.jar:0.11.0]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:541) ~[jjwt-impl-0.11.0.jar:0.11.0]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:601) ~[jjwt-impl-0.11.0.jar:0.11.0]
at io.jsonwebtoken.impl.ImmutableJwtParser.parseClaimsJws(ImmutableJwtParser.java:173) ~[jjwt-impl-0.11.0.jar:0.11.0]
at ir.siavash.customerservice.security.JWTUtil.getAllClaimsFromToken(JWTUtil.java:42) ~[classes/:na]
好的,再一看,就清楚了。这是一个常见的错误。响应式组件可能很难学习,但您离解决方案不远了。
Mono.just 将 预先计算的 值作为参数。因此,您的 getAllClaimsFromToken 将仅在执行所有提供给 just 的代码后创建一个 Mono。这意味着您的错误发生在任何反应组件可用于错误管理(组装时间)之前。
您可以改为使用 Mono#fromCallable 让 Reactor 按需计算 Jwt 令牌,或者仅使用初始字符串创建 Mono,然后使用您的函数进行映射。
让我们看看第二个解决方案:
public Mono<Date> getExpirationDateFromToken(String token) {
return Mono.just(token)
.map(this::getAllClaimsFromToken)
.onErrorResume(ExpiredJwtException.class, e -> Mono.just(e.getClaims()))
.map(Claims::getExpiration);
}
public Claims getAllClaimsFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(Base64.getEncoder().encodeToString(secret.getBytes()))
.build()
.parseClaimsJws(token)
.getBody();
}