Vaadin Flow 14,Jetty 嵌入式和静态文件

Vaadin Flow 14, Jetty embedded and static files

我正在尝试基于 Jetty 9.4.20(嵌入式)和 Vaadin Flow 14.0.12 创建应用程序。

它基于非常好的项目 vaadin14-embedded-jetty

我想用一个 main-jar 打包应用程序,所有依赖库必须在 main-jar 附近的文件夹 'libs' 中。

我删除了 maven-assembly-plugin,而是使用 maven-dependency-pluginmaven-jar-plugin。在 maven-dependency-plugin 中,我添加了部分 <execution>get-dependencies</execution>,其中我将目录 META-INF/resources/,META-INF/services/ 从 Vaadin Flow 库解压缩到结果 JAR。

在这种情况下,应用程序工作正常。但是,如果我评论 <execution>get-dependencies</execution> 部分,则结果包不包含该目录,并且应用程序无法运行。

它只是不能从 Vaadin Flow 库中提供一些静态文件。

仅当我使用...启动打包的应用程序时才会出现此错误

$ java -jar vaadin14-embedded-jetty-1.0-SNAPSHOT.jar

...但是从 Intellij Idea 中它可以正确启动。

有人认为 Jetty 盯着错误的 ClassLoader,无法维护对 Jar-libs 中静态文件的请求。

必须从 Jetty 库维护 META-INF/services/ 文件。

使用 Jetty 很重要java.util.ServiceLoader

如果您将 JAR 文件的内容合并到一个 JAR 文件中,则称为 "uber jar"。

有很多技术可以做到这一点,但是如果您使用 maven-assembly-pluginmaven-dependency-plugin 来构建这个 "uber jar" 那么您将不会合并具有相同名称的关键文件跨多个 JAR 文件。

考虑使用 maven-shade-plugin 及其关联的资源转换器来正确合并这些文件。

ServicesResourceTransformer是合并META-INF/services/个文件的那个,用吧

至于静态内容,效果很好,但您必须正确设置基础资源。

查看您的来源,您执行以下操作...

final URI webRootUri = ManualJetty.class.getResource("/webapp/").toURI();
final WebAppContext context = new WebAppContext();
context.setBaseResource(Resource.newResource(webRootUri));

在 100% 的情况下,这不会可靠地工作(正如您在 IDE vs 命令行中注意到 运行 时所注意到的那样)。

Class.getResource(String) 只有在查找文件(而不是目录)时才可靠。

请考虑 Jetty Project Embedded Cookbook 食谱中的技巧。

参见:

示例:

// Figure out what path to serve content from
ClassLoader cl = ManualJetty.class.getClassLoader();
// We look for a file, as ClassLoader.getResource() is not
// designed to look for directories (we resolve the directory later)
URL f = cl.getResource("webapp/index.html");
if (f == null)
{
    throw new RuntimeException("Unable to find resource directory");
}

// Resolve file to directory
URI webRootUri = f.toURI().resolve("./").normalize();
System.err.println("WebRoot is " + webRootUri);

WebAppContext context = new WebAppContext();
context.setBaseResource(Resource.newResource(webRootUri));