You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确序列化Spring Filter中抛出的Zalando Problem异常

问题根因
  • 你当前配置的@RestControllerAdvice属于Spring MVC组件,仅在DispatcherServlet处理请求的生命周期内生效,只能拦截Controller、MVC拦截器层抛出的异常。
  • Servlet Filter的执行时机早于DispatcherServlet,这一阶段抛出的异常不会进入MVC异常处理链路,会直接抛给Servlet容器走默认错误逻辑,因此Problem不会被正确序列化,状态码也会变成默认的500。
可行解决方案

二选一即可:

方案1:新增前置全局异常捕获Filter(推荐)

新增一个优先级最高的Filter,包裹整个后续Filter链的执行,统一捕获所有下游Filter抛出的Problem异常,用Problem库自带的处理器写入响应,不需要修改现有业务Filter代码。
代码示例:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE) // 设为最高优先级,保证最先进入、最后退出
class GlobalProblemFilter : OncePerRequestFilter() {

    @Autowired
    private lateinit var problemProcessor: ProblemHttpServletResponseProcessor

    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        try {
            filterChain.doFilter(request, response)
        } catch (problem: Problem) {
            problemProcessor.process(response, problem)
        }
    }
}

注意:如果项目集成了Spring Security,需要确认该Filter的执行顺序在Security Filter链之前,否则Security链路抛出的Problem无法被捕获。

方案2:在业务Filter内部自行处理异常

如果不想新增全局Filter,可以直接在你的UserVerifiedFilter中加try-catch逻辑,捕获到Problem后直接写入响应:
修改后的代码示例:

@Component
class UserVerifiedFilter : OncePerRequestFilter() {

    @Autowired
    private lateinit var problemProcessor: ProblemHttpServletResponseProcessor

    @Throws(ServletException::class, IOException::class)
    override fun doFilterInternal(
        request: HttpServletRequest,
        response: HttpServletResponse,
        filterChain: FilterChain
    ) {
        try {
            // 原有业务校验逻辑
            throw Problem.builder()
                .withType(URI.create("https://example.org/email-unverified"))
                .withTitle("Email unverified")
                .withStatus(Status.BAD_REQUEST)
                .withDetail("Email needs to verified to use this endpoint")
                .build()
        } catch (problem: Problem) {
            problemProcessor.process(response, problem)
            return
        }
        filterChain.doFilter(request, response)
    }
}

说明:ProblemHttpServletResponseProcessor是problem-spring-web库提供的内置组件,只要正确引入依赖即可自动注入,无需手动实例化。


内容的提问来源于stack exchange,提问作者edwardmp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 05:33:28