找回密码
 立即注册
首页 业界区 安全 SpringBoot3 WebFlux 拦截器 和 全局异常处理器 ...

SpringBoot3 WebFlux 拦截器 和 全局异常处理器

厨浴 2025-6-8 23:52:17
SpringBoot3 WebFlux 拦截器 和 全局异常处理器

一、拦截器

org.springframework.web.server.CoWebFilter其父类是org.springframework.web.server.WebFilter
webflux 的 拦截器 就像 Servlet 的 Filter 较为原始. 所以Filter咋使用。WebFilter就咋使用。而CoWebFilter是协程环境的Kotlin专用WebFilter,其内部使用mono将Mono转换为了kotlin的挂起函数。
CoWebFilter.kt
  1. abstract class CoWebFilter : WebFilter {
  2.         final override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
  3.                 val context = exchange.attributes[COROUTINE_CONTEXT_ATTRIBUTE] as CoroutineContext?
  4.                 return mono(context ?: Dispatchers.Unconfined) {
  5.                         filter(exchange, object : CoWebFilterChain {
  6.                                 override suspend fun filter(exchange: ServerWebExchange) {
  7.                                         exchange.attributes[COROUTINE_CONTEXT_ATTRIBUTE] = currentCoroutineContext().minusKey(Job.Key)
  8.                                         chain.filter(exchange).awaitSingleOrNull()
  9.                                 }
  10.                         })}.then()
  11.         }
  12.         /**
  13.          * Process the Web request and (optionally) delegate to the next
  14.          * [WebFilter] through the given [WebFilterChain].
  15.          * @param exchange the current server exchange
  16.          * @param chain provides a way to delegate to the next filter
  17.          */
  18.         protected abstract suspend fun filter(exchange: ServerWebExchange, chain: CoWebFilterChain)
  19.         companion object {
  20.                 /**
  21.                  * Name of the [ServerWebExchange] attribute that contains the
  22.                  * [kotlin.coroutines.CoroutineContext] to be passed to the
  23.                  * [org.springframework.web.reactive.result.method.InvocableHandlerMethod].
  24.                  */
  25.                 @JvmField
  26.                 val COROUTINE_CONTEXT_ATTRIBUTE = CoWebFilter::class.java.getName() + ".context"
  27.         }
  28. }
  29. /**
  30. * Kotlin-specific adaption of [WebFilterChain] that allows for coroutines.
  31. *
  32. * @author Arjen Poutsma
  33. * @since 6.0.5
  34. */
  35. interface CoWebFilterChain {
  36.         /**
  37.          * Delegate to the next [WebFilter] in the chain.
  38.          * @param exchange the current server exchange
  39.          */
  40.         suspend fun filter(exchange: ServerWebExchange)
  41. }
复制代码
源码分析:
代码非常简单哈,使用CoWebFilter只需要集成并且实现filter方法即可。
放行

放行只需要调用chain.filter(exchange)即可。并且其可以传递CoroutineContext上下文对象,类似于ThreadLocal.
拦截
  1. val defaultMessage = "token is invalid"
  2. exchange.response.apply {
  3.     statusCode = HttpStatus.UNAUTHORIZED
  4.     headers.contentType = MediaType.APPLICATION_JSON
  5.     val result: edu.tyut.spring_boot_ssm.bean.Result<Boolean> = edu.tyut.spring_boot_ssm.bean.Result.failure(message = defaultMessage, data = false)
  6.     val resultJson: String = objectMapper.writeValueAsString(result)
  7.     val buffer: DataBuffer = bufferFactory().wrap(resultJson.toByteArray(charset = Charsets.UTF_8))
  8.     writeWith(Mono.just<DataBuffer>(buffer)).awaitSingleOrNull()
  9. }.setComplete().awaitSingleOrNull()
复制代码
拦截也是比较简单的的直接在filter方法中调用以上方法即可
work

实现了filter方法,还不会生效。必须满足以下两个条件才可以生效

  • webflux环境
  • 注入bean容器
异常处理器

org.springframework.web.server.CoWebExceptionHandler#CoWebExceptionHandler
这个类是github社区的贡献的。
使用


  • 实现CoWebExceptionHandler
  • 重写coHandle方法
  • 注入容器
  • 提高优先级
案例

GlobalExceptionHandler.kt
  1. @Order(value = -2)
  2. @Component
  3. internal final class GlobalExceptionHandler(
  4. ) : CoWebExceptionHandler() {
  5.     private final val logger: Logger = LoggerFactory.getLogger(this.javaClass)
  6.     override suspend fun coHandle(exchange: ServerWebExchange, ex: Throwable) {
  7.         when (ex) {
  8.             is WebExchangeBindException -> {
  9.                 this.handlerBindException(exchange = exchange, ex = ex)
  10.             }
  11.             else -> {
  12.                 this.handlerOtherException(exchange = exchange, ex = ex)
  13.             }
  14.         }
  15.     }
  16. }
复制代码
TODO

WebFilter 源码解析

WebExceptionHandler 源码解析


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册