如何将WAR包嵌入可运行JAR并通过setWar()方法读取?
嵌入式Jetty加载内嵌WAR包的解决方案
核心逻辑
Jetty的WebAppContext.setWar()支持读取类路径下的资源,只要把WAR包作为类资源打包进可运行JAR,就能通过类加载器获取其路径,实现无外部依赖运行。
一、调整项目结构与Maven配置
1. 放置WAR包
将jersey-servlet.war放到项目的src/main/resources目录(没有就新建),Maven打包时会自动把它加入类路径根目录。
2. 用maven-shade-plugin打包
放弃maven-assembly-plugin,改用maven-shade-plugin处理内嵌资源和依赖,避免类冲突。在pom.xml中添加:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.5.1</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <transformers> <!-- 指定主类,让JAR可直接运行 --> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass>你的包路径.Main</mainClass> </transformer> </transformers> <!-- 排除签名文件,避免打包冲突 --> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> </configuration> </execution> </executions> </plugin> </plugins> </build>
二、修改Java代码读取内嵌WAR
更新Main类,通过类加载器获取内嵌WAR的URL:
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; public class Main { public static void main(String[] args) { Server server = new Server(); ServerConnector connector = new ServerConnector(server); connector.setPort(8088); server.addConnector(connector); WebAppContext context = new WebAppContext(); server.setHandler(context); // 从类路径读取内嵌WAR String warUrl = Main.class.getClassLoader().getResource("jersey-servlet.war").toExternalForm(); context.setWar(warUrl); try { server.start(); server.join(); // 必须调用,否则主线程结束Jetty会立刻停止 } catch (Exception e) { e.printStackTrace(); } } }
三、打包测试
执行Maven命令打包:
mvn clean package
打包完成后,在target目录下找到生成的可运行JAR,直接用java -jar 你的JAR文件名.jar启动即可,无需外部WAR包。
常见问题
- NullPointerException:检查WAR包是否在
src/main/resources下,用jar tf 你的JAR文件名.jar查看JAR内是否包含该WAR。 - 资源访问失败:默认
WebAppContext允许类路径资源加载,无需额外配置,若有自定义配置需检查是否禁用了该功能。 - 类冲突:确保
maven-shade-plugin的过滤器排除了签名文件,上面的配置已处理此问题。
内容的提问来源于stack exchange,提问作者Dan Stone
相关产品推荐
相关产品推荐

