【问题标题】:How to know from where was thrown error 500 (Grails)如何知道从哪里抛出错误 500 (Grails)
【发布时间】:2011-03-30 19:13:54
【问题描述】:

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

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

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

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

有什么想法吗?

提前致谢。

【问题讨论】:

    标签: grails error-handling url-mapping


    【解决方案1】:

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

    class ErrorController {
    
        def show = {
          def exception = request.exception
          render(text: "Exception in ${exception?.className}", 
            contentType: "text/plain", encoding: "UTF-8")
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      更新

      诀窍在于 Grails 将抛出的异常包装到 GrailsWrappedRuntimeException 中,以方便地访问负责异常的代码。在错误控制器中使用以下 sn-p:

      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"
         }
      }
      

      【讨论】:

      • 仍然不知道异常是在AdminController中还是在UserController中引发的,这是我感兴趣的
      • request.getAttribute('exception').className 应该这样做。
      【解决方案3】:

      要显示不同的“错误 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 标签将决定视图中需要包含哪个模板。

      【讨论】:

      • 仍然不知道异常是在AdminController中还是在UserController中引发的,这是我感兴趣的
      • @David: ${request.'javax.servlet.error.message'.encodeAsHTML()} 经常包含Controller的名字,你可以在里面搜索字符串“Controller”,得到之前的第一个点(“。”)并获取子字符串。或者你可以抛出你自己的异常。
      • @David:我认为最好在您发表评论时加入@Hoàng Long,以便我收到通知
      • exception.className 是目标变量,但问题是如何从另一个处理异常页面的控制器而不是视图中获取它。干杯。
      • @AOI Karasu:感谢您指出 exception.className,我没有注意到这种简单的方法 :)。可能我的回答不清楚,但是从控制器或者视图获取是一样的
      【解决方案4】:

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

      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 }}
      

      【讨论】:

        【解决方案5】:

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

        // 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 允许检索控制器,例如,您可以从中提取注释

        【讨论】:

          猜你喜欢
          • 2012-05-09
          • 1970-01-01
          • 1970-01-01
          • 2013-03-17
          • 1970-01-01
          • 2017-01-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多