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

如何向Grails异常处理器传递上下文参数以统一异常处理

当然可以!你完全可以通过自定义异常类携带上下文信息,再配合Grails的异常处理器来消除重复的catch块。下面是具体的实现步骤:

1. 扩展异常类,添加上下文存储能力

首先修改你的WhateverException,让它能够携带每个请求独有的上下文数据:

class WhateverException extends RuntimeException {
    // 用于存储请求上下文的Map
    Map<String, Object> context

    // 重载构造方法,支持传入上下文
    WhateverException(String message, Throwable cause, Map<String, Object> context) {
        super(message, cause)
        this.context = context ?: [:] // 避免空值
    }

    // 可选:添加其他构造方法适配不同场景
    WhateverException(String message, Map<String, Object> context) {
        this(message, null, context)
    }
}

2. 替换控制器中的catch块,改为抛出带上下文的异常

在原来的控制器动作里,去掉重复的catch逻辑,转而在异常发生时(或捕获到原始异常时)抛出携带当前请求上下文的WhateverException:

def someAction() {
    try {
        // 你的业务逻辑代码
        riskyService.doSomething()
    } catch (OriginalBusinessException e) { // 假设原来捕获的是业务层异常
        // 收集当前请求的上下文数据
        def requestContext = [
            foo: request.foo,
            bar: request.baz,
            userId: session.userId // 还可以添加会话等其他上下文
        ]
        // 抛出带上下文的自定义异常
        throw new WhateverException("A whatever error occurred", e, requestContext)
    }
}

3. 实现统一的异常处理器

接下来创建一个异常处理器,统一处理所有WhateverException,负责设置响应状态、记录带上下文的日志:

选项A:控制器级处理器(仅处理当前控制器的异常)

如果只想让这个处理器处理当前控制器的异常,直接在控制器内添加:

import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.http.HttpStatus

class YourController {
    def log

    // 处理当前控制器的WhateverException
    @ExceptionHandler(WhateverException)
    def handleWhateverException(WhateverException ex) {
        // 设置响应状态码
        response.status = HttpStatus.PROPER_HTTP_STATUS.value()
        // 记录带上下文的日志(记得传入异常对象,方便追踪堆栈)
        log.info("A whatever error occurred. Context = ${ex.context}", ex)
        // 可选:返回错误视图或JSON响应
        render([error: ex.message, context: ex.context] as JSON)
    }
}

选项B:全局异常处理器(处理所有控制器的异常)

如果希望所有控制器的WhateverException都由同一个处理器处理,可以创建全局异常处理类:

import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import javax.servlet.http.HttpServletRequest

@ControllerAdvice
class GlobalExceptionHandler {
    def log

    @ExceptionHandler(WhateverException)
    ResponseEntity<Map> handleWhateverException(WhateverException ex, HttpServletRequest request) {
        log.info("A whatever error occurred. Context = ${ex.context}", ex)
        // 构建统一的响应体
        def responseBody = [
            timestamp: new Date().toString(),
            error: ex.message,
            context: ex.context,
            path: request.requestURI
        ]
        // 返回响应实体
        new ResponseEntity<>(responseBody, HttpStatus.PROPER_HTTP_STATUS)
    }
}

关键优势

  • 消除了重复的catch块代码,符合DRY(Don't Repeat Yourself)原则
  • 上下文数据和异常绑定,确保日志能准确反映每个请求的场景
  • 异常处理逻辑集中管理,后续修改日志格式、响应状态等只需调整处理器

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:08:32