Spring 5 Reactive - WebExceptionHandler 没有被调用
Posted
技术标签:
【中文标题】Spring 5 Reactive - WebExceptionHandler 没有被调用【英文标题】:Spring 5 Reactive - WebExceptionHandler is not getting called 【发布时间】:2018-05-17 19:02:27 【问题描述】:我已经尝试了what is the right way to handle errors in spring-webflux 中建议的所有 3 种解决方案,但 WebExceptionHandler
没有被调用。我正在使用Spring Boot 2.0.0.M7
。 Github 仓库here
@Configuration
class RoutesConfiguration
@Autowired
private lateinit var testService: TestService
@Autowired
private lateinit var globalErrorHandler: GlobalErrorHandler
@Bean
fun routerFunction():
RouterFunction<ServerResponse> = router
("/test").nest
GET("/")
ServerResponse.ok().body(testService.test())
@Component
class GlobalErrorHandler() : WebExceptionHandler
companion object
private val log = LoggerFactory.getLogger(GlobalErrorHandler::class.java)
override fun handle(exchange: ServerWebExchange?, ex: Throwable?): Mono<Void>
log.info("inside handle")
/* Handle different exceptions here */
when(ex!!)
is ClientException -> exchange!!.response.statusCode = HttpStatus.BAD_REQUEST
is Exception -> exchange!!.response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR
return Mono.empty()
更新:
当我将 Spring Boot 版本更改为 2.0.0.M2
时,WebExceptionHandler
被调用。我需要为2.0.0.M7
做点什么吗?
解决方案:
按照布赖恩的建议,效果不错
@Bean
@Order(-2)
fun globalErrorHandler() = GlobalErrorHandler()
【问题讨论】:
有人知道如何轻松创建 WebExchangeBindException 吗? 【参考方案1】:您可以提供自己的WebExceptionHandler
,但您必须相对于其他人订购,否则他们可能会在您有机会尝试之前处理错误。
DefaultErrorWebExceptionHandler
(see reference documentation) 订购于-1
Spring Framework 提供的ResponseStatusExceptionHandler
订购地址为0
因此您可以在错误处理组件上添加@Order(-2)
,以便在现有组件之前对其进行排序。
【讨论】:
Spring boot 内置AbstractErrorWebExceptionHandler
似乎对基于网页的应用程序的全局错误处理更友好。对于 REST 应用程序,我认为最好提供类似@RestControllerAdvice
的解决方案来设置 http 状态和实体。
我无法让 RestControllerAdvice 在 DefaultErrorWebExceptionHandler 或自定义 WebExceptionHandler 之前捕获错误...
@Order(-123) 一定要早点解决问spring context apply bean的问题【参考方案2】:
错误响应应具有标准的有效负载信息。这可以通过扩展AbstractErrorWebExceptionHandler
来完成
ErrorResponse:数据类
data class ErrorResponse(
val timestamp: String,
val path: String,
val status: Int,
val error: String,
val message: String
)
ServerResponseBuilder:构建错误响应的 2 种不同方法
默认:处理标准错误webClient:处理 webClient
异常 (WebClientResponseException
),不适用于这种情况
class ServerResponseBuilder(
private val request: ServerRequest,
private val status: HttpStatus)
fun default(): Mono<ServerResponse> =
ServerResponse
.status(status)
.body(BodyInserters.fromObject(ErrorResponse(
Date().format(),
request.path(),
status.value(),
status.name,
status.reasonPhrase)))
fun webClient(e: WebClientResponseException): Mono<ServerResponse> =
ServerResponse
.status(status)
.body(BodyInserters.fromObject(ErrorResponse(
Date().format(),
request.path(),
e.statusCode.value(),
e.message.toString(),
e.responseBodyAsString)))
GlobalErrorHandlerConfiguration:错误处理程序
@Configuration
@Order(-2)
class GlobalErrorHandlerConfiguration @Autowired constructor(
errorAttributes: ErrorAttributes,
resourceProperties: ResourceProperties,
applicationContext: ApplicationContext,
viewResolversProvider: ObjectProvider<List<ViewResolver>>,
serverCodecConfigurer: ServerCodecConfigurer) :
AbstractErrorWebExceptionHandler(
errorAttributes,
resourceProperties,
applicationContext
)
init
setViewResolvers(viewResolversProvider.getIfAvailable emptyList() )
setMessageWriters(serverCodecConfigurer.writers)
setMessageReaders(serverCodecConfigurer.readers)
override fun getRoutingFunction(errorAttributes: ErrorAttributes?): RouterFunction<ServerResponse> =
RouterFunctions.route(RequestPredicates.all(), HandlerFunction<ServerResponse> response(it, errorAttributes) )
private fun response(request: ServerRequest, errorAttributes: ErrorAttributes?): Mono<ServerResponse> =
ServerResponseBuilder(request, status(request, errorAttributes)).default()
private fun status(request: ServerRequest, errorAttributes: ErrorAttributes?) =
HttpStatus.valueOf(errorAttributesMap(request, errorAttributes)["status"] as Int)
private fun errorAttributesMap(request: ServerRequest, errorAttributes: ErrorAttributes?) =
errorAttributes!!.getErrorAttributes(request, false)
【讨论】:
以上是关于Spring 5 Reactive - WebExceptionHandler 没有被调用的主要内容,如果未能解决你的问题,请参考以下文章
Reactive-Spring-Security-5.1.3.RELEASE,多重授权
Spring 5 Reactive 中的 HTTP 响应异常处理
更新到 Spring 5.1 - java.lang.NoClassDefFoundError: org/springframework/http/server/reactive/ServletSer