1

问题的简短版本:什么会导致Scalatra /(Jetty或Tomcat)在不设置请求属性“javax.servlet.error.exception”的情况下将执行传递给ErrorHandler的处理?

更长的上下文:在我最近加入的一个项目中,ErrorHandlers 的句柄方法具有单独的块,用于处理来自“javax.servlet.error.exception”请求属性和所有其他异常的异常。我们在 Jetty 中运行我们的应用程序,据我了解,Jetty 解开 ServletExceptions 并将它们放在上面的属性中。什么会导致处理非“javax.servlet.error.exception”异常的块被调用呢?还是它是多余的并且可以删除?

最初编写代码的人离开了项目。技术堆栈的其余部分是 Scala 和 Scalatra,如果它有什么不同的话。

  Option(request.getAttribute("javax.servlet.error.exception"))
  .map { 
    exception => exception match {
         //various exceptions handled
   }.getOrElse(handleStatusCode(currentStatus))

编辑:似乎在某些环境中,代码在 Tomcat 上运行。

4

2 回答 2

0

我不知道完整的上下文,但我可以想象以下场景。

<servlet-mapping>
  <servlet-name>ErrorPageServlet</servlet-name>
  <url-pattern>/servlet/errorPage/*</url-pattern>
</servlet-mapping>

<error-page>
  <!--unauthorized-->
  <error-code>401</error-code>
  <location>/servlet/errorPage/401</location>
</error-page>

<error-page>
  <!--internal server error-->
  <error-code>500</error-code>
  <location>/servlet/errorPage/500</location>
</error-page>

上面基本上说“对不同类型的 HTTP 错误使用相同的 ErrorPageServlet”。

然后在 servlet 中,您有一个条件来检查是否存在未捕获的异常(查看"javax.servlet.error.exception"请求属性),或者如果没有,则可能是某些原因导致了 HTTP 401。

于 2012-10-05T16:20:02.860 回答
0

在这段代码中发生了几个方法调用,相当于如下:

val a = request.getAttribute("javax.servlet.error.exception")
val b = Option(a)
val c = b.map { exception => /* various exceptions handled... */ }
val d = c.getOrElse(handleStatusCode(currentStatus))

所以,a只是一个普通的 Java 调用。它将在请求中查找指定的属性,并将返回Object映射到该属性的 或null.

因为b我们调用Option构造函数将先前的结果包装在一个 Option 中(这比处理空值更具有 Scala 风格)。因此,如果anull则将bNone,否则它将是Some包含的(非空)值的实例a

在下一行,此选项被映射到一个新值。如果bNone(即anull)那么c也将是None。否则,大括号内的逻辑将应用于 中包含的值b,并将此结果包装在 a 中返回Some

最后,Option 被解包。如果c包含一些值,那么这个值本身就是整个块的结果。否则, iscNone,然后handleStatusCode(currentStatus)被评估,其结果是整个块的结果。


因此,我们可以说当且仅当is => was => was => 请求没有映射到的属性handleStatusCode时才会调用。cNonebNoneanull"javax.servlet.error.exception"

这通常应该是这种情况(例如,在每个非错误请求上)。因此,只有当此块出现在检查中时,删除代码才是安全的,例如:

if (request.getAttribute("javax.servlet.error.exception") != null) {
   ...
   // your posted code
}

即使你要删除它,你会用什么来代替它?Option当为空时应该是什么结果?由于这个原因,调用get()期权通常是一个坏主意。如果你知道它永远不会是空的,你就不需要按照b上面的行来包装它。

于 2012-10-01T16:24:00.483 回答