EDIT2
@paradigmatic 提出了一个很好的建议,即重定向而不是抛出异常;这解决了日志记录问题。Play 2 中的问题是重定向需要在所谓的Action
范围内发生,而日期解析器调用并非总是如此。
作为一种解决方法,我使用了 Play 的全局拦截器,大概相当于 Java servlet 过滤器。
val ymdMatcher = "\\d{8}".r // matcher for yyyyMMdd URI param
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
def ymd2Date(ymd: String) = ymdFormat.parseDateTime(ymd)
override def onRouteRequest(r: RequestHeader): Option[Handler] = {
import play.api.i18n.Messages
ymdMatcher.findFirstIn(r.uri) map{ ymd=>
try { ymd2Date( ymd); super.onRouteRequest(r) }
catch { case e:Exception => // kick to "bad" action handler on invalid date
Some(controllers.Application.bad(Messages("bad.date.format")))
}
} getOrElse(super.onRouteRequest(r))
}
编辑
这里有一点可以使用的上下文:
// String "pimp": transforms ymdString.to_date call into JodaTime instance
class String2Date(ymd: String) {
def to_date = {
import play.api.i18n.Messages
try{ ymdFormat.parseDateTime(ymd) }
catch { case e:Exception => throw new NoTrace(Messages("bad.date.format")) }
}
val ymdFormat = org.joda.time.format.DateTimeFormat.forPattern("yyyyMMdd")
}
@inline implicit final def string2Date(ymd: String) = new String2Date(ymd)
和一个测试自定义异常处理程序:
public class NoTrace extends Exception {
static final long serialVersionUID = -3387516993124229948L;
@Override
public Throwable fillInStackTrace() {
return null;
}
public NoTrace(String message) {
super(message);
}
}
在无效的 yyyyMMdd 字符串上调用日期解析器会将 30 行堆栈跟踪记录到日志中(这发生在 Play 框架/Netty 容器的上游,优于默认的 100 行跟踪):
"20120099".to_date
原始
有一个问题,我的 application.log 充满了与 uri 日期解析器操作相关的错误,如果给定有效的yyyyMMdd
uri 日期,该操作应该成功。
然而,一些用户试图通过输入无效日期来规避这一点,以期获得免费访问仅限付费订阅者的内容。这是没有意义的,因为它根本不起作用,但无论如何,我的应用程序日志中有这些错误跟踪的 MB 数。
有没有办法将一个真正修剪Exception
的日志扔到日志中?我找到了这个 SO 答案,但在我的应用程序中,它看起来像容器(Netty 上的 Play 框架)进入混合状态并将其自己的 30 行堆栈跟踪记录到日志中(30 行优于 100 行,但仍有 29 行太多)
同样,我发现了这个关于 Java 7 的线程和抑制堆栈跟踪的新选项;然而,由于某种原因,尽管在 Java 1.7 上,Eclipse 配置为 Java 1.7,但只有 Throwable 的旧 2 参数方法可用(当我单击 Throwable 类时,我确实看到了 4 参数方法;也许是 Scala 2.9.2 库问题?)
无论如何,理想情况下,我可以简单地记录一条1 行异常消息,而不是厨房水槽。