jar - 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-plugin
and 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 中静态文件的请求。
解决方案
这些META-INF/services/
文件必须从 Jetty 库中维护。
这对 Jetty 使用很重要java.util.ServiceLoader
。
如果您将 JAR 文件的内容合并到一个 JAR 文件中,则称为“uber jar”。
有很多技术可以做到这一点,但是如果您正在使用maven-assembly-plugin
或maven-dependency-plugin
构建这个“超级 jar”,那么您将不会在多个 JAR 文件中合并具有相同名称的关键文件。
考虑使用maven-shade-plugin
和它相关的资源转换器来正确合并这些文件。
- http://maven.apache.org/plugins/maven-shade-plugin/
- http://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html
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食谱有这方面的技术。
看:
- WebAppContextFromClasspath.java
- ResourceHandlerFromClasspath.java
- DefaultServletFileServer.java
- DefaultServletMultipleBases.java
- XmlEnhancedServer.java
- MultipartMimeUploadExample.java
例子:
// 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));
推荐阅读
- powerbi - 记分卡上具有数字精度的小数
- javascript - 如何使用forEach用来自json的迭代数据填充矩阵?
- python - tensorflowjs_converter 可以与使用功能 API 制作的 Keras 模型一起使用吗?
- bash - 有没有办法从命令行(FreeBSD/Darwin)将字符串发送到 IPC 套接字?
- python - 在 for 循环的每个循环中向 df 添加一个新列
- python-3.x - RobotFramework(python 3):AppiumLibrary:打开应用程序> InsecureRequestWarning
- python - 如何将一列数据框的所有元素设置为数组?
- c - “下标需要数组或指针”错误
- tensorflow - TensorFlow 映射通道,同时保持其他维度
- r - r 通过填充行值来扩展 data.table 列