如何使用嵌入式码头从web.xml加载servlet?

问题描述 投票:0回答:1

我正在尝试将我的应用程序从tomcat迁移到嵌入式码头。我已经按照一些指南(thisthisthis等)在Web模块中创建了一个入口点。结果文件显示如下:

import org.eclipse.jetty.server.Server
import org.eclipse.jetty.webapp.WebAppContext

object EPILauncher extends App {
  val server: Server = new Server(8080)
  val coolWebApplication = new WebAppContext()
  coolWebApplication.setResourceBase("warehouse/src/main/webapp/")
  coolWebApplication.setContextPath("/api")
  coolWebApplication.setDescriptor("warehouse/src/main/webapp/WEB-INF/web.xml")
  coolWebApplication.setParentLoaderPriority(true)
  server.start()
  System.out.println("Started!")
  server.join()
}

我在web.xml文件中有以下servlet声明

     <servlet>
        <servlet-name>CustomerApplication</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.xxxx.yyyy.warehouse.web.Root</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>
                io.swagger.jaxrs.listing,
                org.owasp.csrfguard.servlet,
                com.xxxx.yyyy.warehouse.resource
            </param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.scanning.recursive</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.servlet.filter.staticContentRegex</param-name>
            <param-value>.*(html|css|js|eot|svg|ttf|woff)</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>CustomerApplication</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

com.xxxx.yyyy.warehouse.resource包含实现,例如:

@Singleton
@Path("/settings")
@Api("/settings")
class SettingsResource @Inject()(config: Config) {
  @GET
  @Path("/version")
  @Produces(Array(MediaType.APPLICATION_JSON))
  def getBackendVersion(@Context servletContext: ServletContext): Response = {
    val manifestStream = servletContext.getResourceAsStream("META-INF/MANIFEST.MF")
    val version: String = Option(manifestStream)
      .map(Utils.using(_) { is =>
        val attrs = new java.util.jar.Manifest(is).getMainAttributes
        val version = attrs.getOrDefault(new Attributes.Name("Specification-Version"), "local-version").toString
        val build = attrs.getOrDefault(new Attributes.Name("Implementation-Version"), "local-build").toString
        s"$version.$build"
      }).getOrElse("local-version.local-build")
    Response.ok(VersionInfo(version)).build()
  }
}

所以,当我运行我的应用程序并导航到localhost:8080/api/settings/version时,我看到的是:

URI:    /api/settings/version
STATUS: 404
MESSAGE:    Not Found
SERVLET:    -

所以,我认为我不太了解某些概念。我应该明确指出我要使用的main方法吗?它们可以从web.xml文件自动加载吗?谢谢。

tomcat servlets jetty web.xml embedded-jetty
1个回答
1
投票

虽然您可以从WEB-INF/web.xml或注释中加载servlet,但这不是使用嵌入式服务器的最理想方法。

为什么?

对于码头,要使用WEB-INF/web.xml或注释,请使用WebAppContext。这是一个重量级的组件,具有完整的Servlet规则和类加载器行为(例如:类加载器隔离)。

对于嵌入式服务器,这通常是多余的。

接下来,如果您依赖注释,那么您将需要对拥有的类进行字节码扫描,从而使环境的设置更加复杂。

Jetty上更传统的设置是使用ServletContextHandler,而不是WebAppContext并手动声明所有Servlet和过滤器及其映射。

这也使启动非常快(适用于docker环境或微服务)。考虑一下亚秒级启动。这样,只需花费很少的精力就可以实现100ms的启动。

如果必须坚持使用战争和WebAppContext,请考虑对战争配置和资源进行构建时扫描,然后将jetty-quickstart元数据添加到战争中。那小段XML,加上quickstart运行时,也将使您无需任何webapp发现步骤即可快速启动。

© www.soinside.com 2019 - 2024. All rights reserved.