如何避免Grails中Micronaut声明式客户端的异常堆栈被RecoveryInterceptor记录
解决Micronaut声明式客户端403异常时避免RecoveryInterceptor输出完整堆栈的方法
当使用Micronaut声明式客户端遇到403 Forbidden响应时,默认的RecoveryInterceptor会打印完整的异常堆栈日志,以下几种方法可以解决这个问题:
方法1:用@Error注解自定义异常处理
在Grails项目中创建全局异常处理类,捕获HttpClientResponseException并控制日志输出格式,替代默认的异常处理逻辑:
import io.micronaut.http.client.exceptions.HttpClientResponseException import io.micronaut.http.annotation.Error import org.slf4j.Logger import org.slf4j.LoggerFactory class TelegramExceptionHandler { private static final Logger log = LoggerFactory.getLogger(TelegramExceptionHandler) @Error(exception = HttpClientResponseException.class, global = true) void handleTelegramForbidden(HttpClientResponseException e) { // 仅输出简洁的错误提示,不打印完整堆栈 log.warn("Telegram API请求被拒绝: {}", e.message) // 若需给调用方返回响应,可返回自定义HttpResponse // return HttpResponse.status(e.status).body("请求Telegram服务被拒绝") } }
配置后,RecoveryInterceptor不会再输出默认的堆栈日志,异常会被自定义逻辑处理。
方法2:自定义ClientFilter拦截403响应
创建客户端过滤器,在响应到达业务代码前拦截403状态,直接处理或转换响应,避免抛出触发堆栈日志的异常:
import io.micronaut.http.HttpResponse import io.micronaut.http.MutableHttpRequest import io.micronaut.http.annotation.Filter import io.micronaut.http.client.filter.ClientFilter import io.micronaut.http.filter.FilterChain import org.reactivestreams.Publisher import org.slf4j.Logger import org.slf4j.LoggerFactory @Filter("/sendMessage") // 仅针对Telegram的sendMessage接口生效 class TelegramClientFilter implements ClientFilter { private static final Logger log = LoggerFactory.getLogger(TelegramClientFilter) @Override Publisher<? extends HttpResponse<?>> doFilter(MutableHttpRequest<?> request, FilterChain chain) { return chain.proceed(request).map(response -> { if (response.status.code == 403) { log.warn("Telegram API请求被禁止,状态码: {}", response.status.code) // 若无需抛出异常,直接返回当前响应即可;如需抛出自定义异常,可在此处抛出 return response } return response }) } }
这种方式在请求链路的早期处理了403响应,不会触发RecoveryInterceptor的异常日志逻辑。
方法3:调整日志配置抑制堆栈输出
直接修改日志配置文件,降低RecoveryInterceptor的日志级别,使其仅输出警告信息而不打印堆栈:
若使用logback.groovy:
logger("io.micronaut.http.client.interceptor.RecoveryInterceptor", WARN, ["STDOUT"], false)
若使用application.yml:
logging: level: io.micronaut.http.client.interceptor.RecoveryInterceptor: WARN
该方法最简单,但会对所有使用RecoveryInterceptor的客户端生效,适合不需要针对单个接口特殊处理的场景。
内容的提问来源于stack exchange,提问作者user2572790
相关产品推荐
相关产品推荐

