首页 > 解决方案 > Vaadin Flow 14,Jetty 嵌入式和静态文件

问题描述

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

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

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

我删除maven-assembly-plugin,而不是使用maven-dependency-pluginand maven-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 中静态文件的请求。

标签: jarclassloaderembedded-jettyvaadin-flow

解决方案


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

这对 Jetty 使用很重要java.util.ServiceLoader

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

有很多技术可以做到这一点,但是如果您正在使用maven-assembly-pluginmaven-dependency-plugin构建这个“超级 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 与命令行中运行时所注意到的那样)。

只有在查找文件(而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));

推荐阅读