7

我的 UrlMappings.groovy 中有下一个场景:

"/user/$action?" (controller:"user")
"/admin/$action?" (controller:"user")

"500"(controller:"error", action:"show")
"404"(controller:"error", action:"show")

而且我需要知道 errorController 从哪个控制器引发了引发错误 500 的异常(如果有),并为用户和管理员显示不同的错误页面。

有任何想法吗?

提前致谢。

4

5 回答 5

13

您可以通过访问 ErrorController 中的异常request.exception。顶级异常始终指向引发它的控制器,因此您可以使用exception.className. 这是一个非常简单的例子。

class ErrorController {

    def show = {
      def exception = request.exception
      render(text: "Exception in ${exception?.className}", 
        contentType: "text/plain", encoding: "UTF-8")
    }
}
于 2011-03-31T08:52:23.483 回答
8

使用request.getAttribute("exception")您将获得例外。我会查看所有请求属性,也许有对原始控制器的直接引用。

更新

诀窍在于 Grails 将抛出的异常包装到GrailsWrappedRuntimeException 中,从而提供对负责异常的代码的舒适访问。在错误控制器中使用以下代码段:

import org.codehaus.groovy.grails.web.errors.GrailsWrappedRuntimeException
def action = {   
   def exception = request.getAttribute('exception')
   if (exception instanceof GrailsWrappedRuntimeException) {
       log.error "exception $exception.className, line $exception.lineNumber has throw $exception.cause"
   }
}
于 2011-03-30T21:09:51.270 回答
1

要显示不同的“错误 500”页面,我认为您可以对 Grails 脚手架执行相同的操作:

首先,我们只需要在 URL Mapping 中指定视图:

"500"(view: "/500")   // Point to 500.gsp

然后是“500”视图代码:

        <h1>Grails Runtime Exception</h1>

        <h2>Error Details</h2>

        <div class="message">
            <strong>Error ${request.'javax.servlet.error.status_code'}:</strong>
            ${request.'javax.servlet.error.message'.encodeAsHTML()}<br/>
            <strong>Servlet:</strong> ${request.'javax.servlet.error.servlet_name'}<br/>
            <strong>URI:</strong> ${request.'javax.servlet.error.request_uri'}<br/>
            <g:if test="${exception}">
                <strong>Exception Message:</strong> ${exception.message?.encodeAsHTML()} <br/>
                <strong>Caused by:</strong> ${exception.cause?.message?.encodeAsHTML()} <br/>
                <strong>Class:</strong> ${exception.className} <br/>
                <strong>At Line:</strong> [${exception.lineNumber}] <br/>
                <strong>Code Snippet:</strong><br/>

                <div class="snippet">
                    <g:each var="cs" in="${exception.codeSnippet}">
                        ${cs?.encodeAsHTML()}<br/>
                    </g:each>
                </div>
            </g:if>
        </div>
        <g:if test="${exception}">
            <h2>Stack Trace</h2>

            <div class="stack">
                <pre><g:each in="${exception.stackTraceLines}">${it.encodeAsHTML()}<br/></g:each></pre>
            </div>
        </g:if>

您可以从错误和堆栈跟踪(div class="stack")中提取您需要的任何信息。

您可以为用户和管理员制作 2 个不同的模板,然后一个g:if标签将决定视图中需要包含哪个模板。

于 2011-03-31T03:56:30.463 回答
0

您可以通过请求属性访问处理错误请求的控制器实例,org.codehaus.groovy.grails.CONTROLLER例如(在 GSP 中):

Controller: ${request['org.codehaus.groovy.grails.CONTROLLER']}

要获取控制器的名称:

Controller name: ${request['org.codehaus.groovy.grails.CONTROLLER_NAME_ATTRIBUTE']}

我在 Grails 2.0 和 2.2 中对此进行了测试,但在任何地方都找不到它的文档,因此在不同版本的 Grails 中可能会有所不同。要查看请求中可用的所有属性,请将以下内容添加到error.gsp

${${request.findAll { true }}
于 2013-03-11T14:05:02.593 回答
0

我有时会用我想在错误消息中显示的描述来注释我的控制器:

// ControllerType is a custom annotation
@ControllerType(description= "this does foo bar")
class MainController {
    ...

有了这些,并根据 Aoi Karasu 的帖子,以下是如何从初始控制器中提取信息:

class ErrorsController {
def index() {
    def initialController = request.exception?.className
    if (initialController) {
        def controller = grailsApplication.getArtefact("Controller", initialController).getReferenceInstance()
        render "Controller: ${initialController}, annotations ${controller.getClass().getDeclaredAnnotations()}"
        return
    }
    render 'no initial controller'
}

}

request.exception?.className结合grailsApplication.getArtefact允许检索控制器,例如,您可以从中提取注释

于 2013-11-19T15:53:01.610 回答