在我的Scalatra路线中,我经常使用halt()
快速失败:
val user: User = userRepository.getUserById(params("userId"))
.getOrElse {
logger.warn(s"Unknown user: $userId")
halt(404, s"Unknown user: $userId")
}
如示例所示,我还想在这些情况下记录警告。但我想避免halt()和记录器之间的代码重复。简单地做起来会更加清洁:
val user: User = userRepository.getUserById(params("userId"))
.getOrElse(halt(404, s"Unknown user: $userId"))
以交叉方式记录所有“HaltExceptions”的最佳方式是什么?
我考虑过:
1)覆盖路线中的halt()
方法:
override def halt[T](status: Integer, body: T, headers: Map[String, String])(implicit evidence$1: Manifest[T]): Nothing = {
logger.warn(s"Halting with status $status and message: $body")
super.halt(status, body, headers)
}
除了奇怪的方法签名之外,我不太喜欢这种方法,因为我可能会错误地调用真实halt()
而不是重写方法,例如,如果我在路线外停止。在这种情况下,不会记录任何警告。
2)使用trap()
记录所有错误响应:
trap(400 to 600) {
logger.warn(s"Error returned with status $status and body ${extractBodyInSomeWay()}")
}
但我不确定这是最好的方法,特别是因为它向_statusRoutes
Map添加了201个路由(范围内每个整数的一个映射...)。我也不知道如何在这里提取身体?
3)在Jetty中启用某种响应日志记录以获取特定的状态代码吗?
这样做的最佳方法是什么?我是否正确接近这个?
答案 0 :(得分:1)
最简单的解决方案是在servlet过滤器中进行,如下所示:
package org.scalatra.example
import javax.servlet._
import javax.servlet.http.HttpServletResponse
class LoggingFilter extends Filter {
override def init(filterConfig: FilterConfig): Unit = ()
override def destroy(): Unit = ()
override def doFilter(request: ServletRequest, response: ServletResponse, chain: FilterChain): Unit = {
chain.doFilter(request, response)
val status = response.asInstanceOf[HttpServletResponse].getStatus
if (status >= 400 && status <= 600) {
// Do logging here!
}
}
}
在Bootstrap课程中注册此过滤器(或者甚至可以在web.xml
中注册):
package org.scalatra.example
import org.scalatra._
import javax.servlet.ServletContext
class ScalatraBootstrap extends LifeCycle {
override def init(context: ServletContext): Unit = {
context.addFilter("loggingFilter", new LoggingFilter())
context.getFilterRegistration("loggingFilter")
.addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
// mount your servlets or filters
...
}
}
在我看来,Scalatra应该提供一种基本上更容易陷阱的方法。事实上,在renderHaltException
中有一个名为ScalatraBase
的方法,它看起来可以通过一键覆盖此方法来添加日志记录:
https://github.com/scalatra/scalatra/blob/cec3f75e3484f2233274b1af900f078eb15c35b1/core/src/main/scala/org/scalatra/ScalatraBase.scala#L512
但是我们实际上无法做到这一点,因为HaltException
是包私有的,只能在org.scalatra
包内访问。我想我应该公开HaltException
。