簡體   English   中英

如何讓 Jetty 掃描 class 路徑中的 Maven 依賴項 jar 文件?

[英]How can I get Jetty to scan the Maven dependency jar files in the class path?

Eclipse 自動將所有 Maven 依賴項添加到 class 路徑。

當從 Z32F725220269696DZ 片段開始時,如何讓 Jetty 掃描 web 片段的 class 路徑上的 jar 文件?

當打包並放置在 webapp/WEB-INF/lib/*.jar 中時,掃描工作。

Server server = new Server(8080);

WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/myapp");
webapp.setBaseResource(Resource.newResource(new File("webapp")));

// https://stackoverflow.com/questions/11768113/cant-get-jetty-to-scan-for-annotated-classes
webapp.setConfigurations(new Configuration[] { //
    new AnnotationConfiguration(), // @WebServlet, @WebListener...
    new WebXmlConfiguration(), // webapp/WEB-INF/web.xml
    new WebInfConfiguration(), // ?
    new MetaInfConfiguration(), // ?
    new FragmentConfiguration(), // e.g. zkwebfragment-9.6.0.1.jar!/META-INF/web-fragment.xml
});

if(RUNNING_FROM_IDE)
{
  // add project classes to classpath (e.g. target/classes)
  webapp.getMetaData().setWebInfClassesDirs(Arrays.asList(Resource.newResource(MyAppMainClass.class.getProtectionDomain().getCodeSource().getLocation())));

  // how to add maven dependencies?
  // webapp.getMetaData().addWebInfJar(???);
}

server.setHandler(webapp);
server.start();

不要手動設置配置,這是第一個錯誤。

您的努力基本上破壞了配置,因為您不尊重原始默認配置或微妙的訂單要求。

這是錯誤的方式,直接設置 webapp 配置。

webapp.setConfigurations(new Configuration[] { //
    new AnnotationConfiguration(), // @WebServlet, @WebListener...
    new WebXmlConfiguration(), // webapp/WEB-INF/web.xml
    new WebInfConfiguration(), // ?
    new MetaInfConfiguration(), // ?
    new FragmentConfiguration(), // e.g. zkwebfragment-9.6.0.1.jar!/META-INF/web-fragment.xml
});

這是正確的方法,通過在服務器級別調整默認配置列表。

Configuration.ClassList classlist = Configuration.ClassList
  .setServerDefault(server);
classlist.addBefore(
  "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
  "org.eclipse.jetty.annotations.AnnotationConfiguration");

這應該足夠了。

您可以在服務器轉儲中查看默認配置順序。

server.setDumpAfterStart(true);
server.start();
// and then on the output (see your logger) ...
|  |  |  +> Configurations Servlet Dump WebApp@4c163e3 size=5
|  |  |  |  +> org.eclipse.jetty.webapp.WebInfConfiguration@5e403b4a
|  |  |  |  +> org.eclipse.jetty.webapp.WebXmlConfiguration@5117dd67
|  |  |  |  +> org.eclipse.jetty.webapp.MetaInfConfiguration@5be49b60
|  |  |  |  +> org.eclipse.jetty.webapp.FragmentConfiguration@2931522b
|  |  |  |  +> org.eclipse.jetty.webapp.JettyWebXmlConfiguration@7674b62c
|  |  |  +> Handler attributes Servlet Dump WebApp@4c163e3 size=3

此轉儲功能很有用,因為它可能會告訴您$HOME/.m2/repository jar 文件不存在於 webapp 自己的類路徑中。

|  |  |  +> WebAppClassLoader{Servlet Dump WebApp}@5fb759d6
|  |  |  |  +> URLs size=1
|  |  |  |  |  +> file:/tmp/jetty-0_0_0_0-8080-ROOT_war-_-any-15598896298108484560/webapp/WEB-INF/classes/

如果您在此處看不到 maven 存儲庫文件,那么您應該在啟動 webapp 之前配置WebAppContext.setExtraClasspath(String)以包含它們。

另一個需要注意的功能是 2 個掃描正則表達式,用於識別哪些內容(類文件)被掃描。 一個用於 webapp 類,一個用於服務器類。 Both of these are relevant for the discovery of anything in the servlet spec, be it annotated listeners, annotated servlets, web fragments, servlet container initializers, jsp level details, websocket level details, etc)

如果要配置它們,兩者都設置為WebAppContext.setAttribute(String key, String value)上的屬性。

默認情況下,這些值為空,這意味着掃描所有 jars。

// This one controls server/container level discovery.

// An example of limited scanning would be
webappContext.setAttribute(
  "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern"
  ".*/[^/]*servlet-api-[^/]*\\.jar$|.*[^/]*jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$");


// This one controls webapp specific discovery.
webappContext.setAttribute(
  "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern"
  ".*/[^/]*foo-[^/]*\\.jar$|.*/[^/]*bar.*\\.jar$");

這方面的一個例子是......

你有一個帶有...的網絡應用程序

WEB-INF/lib/
           foo-api-1.2.3.jar
           foo-1.2.3.jar
           bar-0.9.jar
           boo-1.0.jar

並定義了 webapp 掃描,如......

webappContext.setAttribute(
    "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern",
    ".*/.*foo-api-[^/]\.jar$|./.*bar-[^/]\.jar$|./.*wibble[^/]*\.jar$");

然后將匹配並掃描以下文件:

WEB-INF/lib/
           foo-api-1.2.3.jar
           bar-0.9.jar

我讓它以某種方式工作。 仍然想知道是否有更標准的方法來實現這一點:

// launching from IDE: manually add WEB-INF/classes and WEB-INF/lib/*.jar entries
webapp.getMetaData().setWebInfClassesDirs(Arrays.asList(Resource.newResource(MyAppMainClass.class.getProtectionDomain().getCodeSource().getLocation())));
for(URL url : ((URLClassLoader) MyAppMainClass.class.getClassLoader()).getURLs()) {
  if(url.getPath().endsWith(".jar")) {
    webapp.getMetaData().addWebInfJar(Resource.newResource(url));
  }
}

我還在jetty-maven-plugin中找到了MavenWebInfConfiguration 我使用:

((WebAppClassLoader)  webapp.getClassLoader()).addClassPath(...)

根據 Joakim 的回答,我現在有:

Server server = new Server(port);
Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
classlist.addAfter(JettyWebXmlConfiguration.class.getName(), AnnotationConfiguration.class.getName());

WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/myapp");
webapp.setBaseResource(Resource.newResource(new File(isRunningFromIde ? "./webapp" : "/path/to/webapp").getCanonicalFile()));    
webapp.setWelcomeFiles(new String[] { "index.html" });
//    webapp.setInitParameter(..., ...));
//    webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", "");
//    webapp.setAttribute("org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern", "");

if(isRunningFromIde)
{
  List<String> extraClassPath = new ArrayList<>();
  // target/classes
  extraClassPath.add(Paths.get(MyAppMain.class.getProtectionDomain().getCodeSource().getLocation().toURI()).toString());
  // maven dependencies
  for(URL url : ((URLClassLoader) MyAppMain.class.getClassLoader()).getURLs()) {
    if(url.getPath().endsWith(".jar")) {
      extraClassPath.add(Paths.get(url.toURI()).toString());
    }
  }
  webapp.setExtraClasspath(extraClassPath.stream().collect(Collectors.joining(";")));
}

server.setHandler(webapp);
server.setDumpAfterStart(true);
server.start();

感謝服務器轉儲提示,我想我現在也明白為什么我會從 ZK 收到復制資源警告 WebAppClassLoader 和 AppClassLoader 都包含相同的條目。 由於上述額外的類路徑,IDE 啟動。 docker 容器可能是因為我用java -cp <webapp>/WEB-INF/lib/* MyAppMain.class啟動它。

|  +> WebAppClassLoader{403716510}@1810399e
|  |  +> URLs size=41
|  |  |  +> file:<maven-repo-or-webapp-dir>/WEB-INF/lib/zk-9.6.0.1.jar
|  |  |  ...
|  |  +> sun.misc.Launcher$AppClassLoader@4e0e2f2a
|  |  |  +> URLs size=41
|  |  |  |  +> file:<maven-repo-or-webapp-dir>/WEB-INF/lib/zk-9.6.0.1.jar
|  |  |  |  ...

嘗試 3(也基於 Joakim 的回答):設置 ContainerIncludeJarPattern 以掃描類路徑中已經存在的所有內容。 無需任何額外的 class 路徑修改。

    Server server = new Server(8080);
    WebAppContext webapp = new WebAppContext();
    webapp.setContextPath("/test");
    webapp.setBaseResource(Resource.newResource(new File("webapp").getCanonicalFile()));
    // https://www.eclipse.org/jetty/documentation/jetty-9/index.html#configuring-webapps
    // order apparently important
    webapp.setConfigurations(new Configuration[] { //
        new WebInfConfiguration(), //
        new WebXmlConfiguration(), //
        new MetaInfConfiguration(), //
        new FragmentConfiguration(), //
        new AnnotationConfiguration(), //
    });
    webapp.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*");
    server.setHandler(webapp);
    server.setDumpAfterStart(true);
    server.start();

我的其他問題似乎與 ZK 有關,所以我為此提出了一個新問題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM