如何在启动时初始化()/初始化()Scalatra servlet?

时间:2014-01-14 23:36:45

标签: tomcat scalatra

我们发现当从开发中的Jetty转移到生产中的Tomcat时,我们的Swagger文档停止工作 - 在第一次调用提供操作的servlet之后,Swagger文档中不会显示任何操作。

在调试器中完成一些工作后,我们将问题跟踪到servlet的init()方法未被调用。我假设Jetty将所有servlet视为load-on-startup,而Tomcat则不是,除非你在web.xml中明确告诉它。

不幸的是,在web.xml中,你可以设置为load-on-startup的唯一东西是servlet,而我们的Scalatra web.xml中没有实际的servlet,只有监听器和servlet映射。

我们怎样才能让Scalatra在启动时初始化我们的各种ScalatraServlets


注意:我们使用的是Scalatra 2.2.2。很可能转向2.3快照或里程碑会解决Swagger问题,但我们已经做了很多工作来使2.2 Swagger集成工作,我们太接近了,不能全力以赴。 / p>

1 个答案:

答案 0 :(得分:2)

编辑:这已进入Scalatra,应尽快推出,请参阅https://github.com/scalatra/scalatra/pull/356

是的,默认情况下,Tomcat在第一次发出HTTP请求之前不会加载Servlet。您可以使用load-on-startup告诉Tomcat加载Servlet。以下是使用LifeCycle编程方式执行此操作的方法:

def mountServlet(sc: ServletContext, servlet: HttpServlet, urlPattern: String, loadOnStartup: Int = 1) {
  val name = servlet.getClass.getName
  val reg = Option(sc.getServletRegistration(name)) getOrElse {
    val r = sc.addServlet(name, servlet)
    servlet match {
      case s: HasMultipartConfig =>
        r.setMultipartConfig(s.multipartConfig.toMultipartConfigElement)
      case _ =>
    }
    if (servlet.isInstanceOf[ScalatraAsyncSupport])
      r.setAsyncSupported(true)
    r.setLoadOnStartup(loadOnStartup)
    r
  }

  reg.addMapping(urlPattern)
}

这定义了RichServletContextmount方法的替代方法。重要的部分是r.setLoadOnStartup(loadOnStartup)

你可以像这样使用它:

override def init(context: ServletContext) {

  val comments = CommentsRepository(mongoColl)

  // mount the api + swagger docs
  mountServlet(context, new CommentsApi(comments), "/api/*", 1)
  mountServlet(context, new CommentsApiDoc(), "/api-docs/*", 2)

  mountServlet(context, new CommentsFrontend(comments), "/*")

}

示例代码取自https://github.com/scalatra/scalatra-in-action/blob/d325c85feaf10706951c8edb88a3d82d0488faf3/comments-collector/src/main/scala/ScalatraBootstrap.scala