我们发现当从开发中的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>
答案 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)
}
这定义了RichServletContext
中mount
方法的替代方法。重要的部分是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), "/*")
}