Grails中自定义ErrorController适配MVC/REST请求及租户拦截器兼容方案咨询
Grails自定义ErrorController统一处理异常解决方案
问题背景
配置"500"(controller : "error", action : "index")时,会触发检查TenantID的拦截器导致异常;尝试用"500"(uri:"/${tenantID}/error/index")的映射方式却不生效,Grails仍返回默认500错误页面。
解决方案
方案1:排除拦截器对ErrorController的拦截
直接在TenantID拦截器里排除ErrorController的所有请求,这样原来的500映射就能正常工作,不会被拦截逻辑干扰:
class TenantInterceptor { TenantInterceptor() { match(controller: '*', action: '*') exclude(controller: 'error') // 跳过ErrorController的所有请求 } boolean before() { // 原有的TenantID校验逻辑 // ... } }
方案2:调整UrlMappings并手动处理TenantID
如果必须保留带TenantID的路由结构,按以下步骤调整:
- 修改UrlMappings,确保错误路由能正确传递TenantID参数:
class UrlMappings { static mappings = { // 先定义业务路由,保证TenantID能被正常解析 "/$tenantID/$controller/$action?/$id?(.$format)?"{ // 业务路由的约束配置 // ... } // 配置500错误路由,传递TenantID参数 "500"(controller: "error", action: "index") } }
- 在ErrorController的index方法中,从请求属性或参数中获取TenantID,并根据请求类型返回对应响应:
class ErrorController { def index() { // 优先从请求属性拿TenantID(如果拦截器已经解析过),没有再从参数取 def tenantID = request.getAttribute('tenantID') ?: params.tenantID // 判断请求类型,返回REST或MVC响应 def isRestRequest = request.xhr || request.format in ['json', 'xml'] if (isRestRequest) { render status: 500, contentType: 'application/json', text: [error: '服务器内部错误', tenant: tenantID] as JSON } else { render view: 'index', model: [tenantID: tenantID] } } }
- 确认
grails-app/conf/application.yml中grails.exceptionresolver.enabled设置为true(默认开启,无需修改),保证自定义错误处理生效。
官方文档相关内容翻译
映射到响应码
在Grails中,你可以通过UrlMappings将HTTP响应码映射到特定的控制器动作或URI,以此为不同错误场景自定义响应内容。
基础的响应码映射格式示例:
"404"(controller: "notFound") "500"(uri: "/error.html")当服务器返回对应HTTP状态码时,Grails会使用指定的控制器动作或URI生成响应。需要注意的是,响应码映射的优先级低于常规路由,要确保错误路由的定义不会被其他路由覆盖。另外,你还可以在映射中传递参数,或者根据请求特性(如格式、请求类型)调整响应逻辑。
内容的提问来源于stack exchange,提问作者Akshay Kabra
相关产品推荐
相关产品推荐

