【问题标题】:spring WebFilter overrides ExceptionHandler headerspring WebFilter 覆盖 ExceptionHandler 标头
【发布时间】:2018-12-20 13:04:03
【问题描述】:

我同时使用了 WebFilter 和 WebExceptionHandler。 仅当 ExceptionHandler 未设置时,WebFilter 才应添加新标头。 但是,WebFilter是在WebHttpHandler执行ExceptionHandler之前添加到ServerWebExchange中的,所以无法判断ExceptionHandler是否被触发。

@Component
@Order(-2)
class MyErrorWebExceptionHandler(g: MyErrorAttributes, applicationContext: ApplicationContext, serverCodecConfigurer: ServerCodecConfigurer)
    : AbstractErrorWebExceptionHandler(g, ResourceProperties(), applicationContext) {

    init {
        super.setMessageWriters(serverCodecConfigurer.writers)
        super.setMessageReaders(serverCodecConfigurer.readers)
    }

    @Override
    override fun getRoutingFunction(errorAttributes: ErrorAttributes): RouterFunction<ServerResponse> {
        return RouterFunctions.route(RequestPredicates.all(), HandlerFunction<ServerResponse> { renderErrorResponse(it) })
    }

    private fun renderErrorResponse(request: ServerRequest): Mono<ServerResponse> {

        val errorPropertiesMap = getErrorAttributes(request, false)

        return ServerResponse.status(HttpStatus.OK)
                .contentType(MediaType.APPLICATION_JSON_UTF8)
                .headers { x ->
                        x.set(c_ApplicationStatus, errorPropertiesMap[c_ApplicationStatus].toString())
                      }.build()
}

@Component
class ServerResponseHeaderWebFilter : WebFilter {
    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        exchange.response.headers.set(c_ApplicationStatus, HttpStatus.OK.value().toString())
        return chain.filter(exchange)

    }
}

【问题讨论】:

    标签: java kotlin spring-webflux


    【解决方案1】:

    在这种情况下,我们可以快速建模执行顺序,例如:

    WebFilter
    |- setting the application status header to OK
    |- calling chain.filter
       |- finding the handler and calling it
       |- in case of an error, the exception handler is called
    |- after chain.filter
    

    过滤器链完成交换后,响应已提交并处理,因此此时无法更改响应标头。使用此代码示例,异常处理程序(如果执行)将覆盖 Web 过滤器设置的任何标头。

    所以从技术上讲,您的问题的答案是,一旦处理程序链处理完响应,就无法修改它。这是 Spring WebFlux 设计的预期行为。

    但听起来我们需要退后一步,谈谈你想要实现的目标。

    您是否在开发功能时尝试检查您的异常处理程序是否被调用? 您是否正在尝试以某种目前无法实现的方式调整 Spring Boot 中的错误处理机制?

    如果您想谈谈您想要实现的目标,请提出另一个问题,以便 SO 用户可以从这个问题中受益。

    【讨论】:

    • 嗯,我认为这种流程会发生,但实际上并没有。
    • 抱歉,上一条消息已被截断。为清楚起见,假设我的过滤器将标头设置为 OK,错误异常处理程序将其设置为 ERROR。在我的测试中,无论是否调用异常处理程序,我总是收到 OK 标头。看起来 chain.filter(exchange) 仅在调用异常处理程序后才应用,覆盖标头内容。
    【解决方案2】:

    最终我发现过滤器中设置的标头可以在 request.exchange() 对象中看到。必须将其删除,以便新的标头集替换它。

    private fun renderErrorResponse(request: ServerRequest): Mono<ServerResponse> {
    
            val errorPropertiesMap = getErrorAttributes(request, false)
    
            request.exchange().response.headers.remove(c_ApplicationStatus)
            return ServerResponse.status(HttpStatus.OK)
                    .contentType(MediaType.APPLICATION_JSON_UTF8)
                    .headers { x -> x.set(c_ApplicationStatus, value) }
                    .build()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-21
      • 2019-07-19
      • 2018-11-28
      • 2011-04-17
      • 2012-09-06
      • 2016-08-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多