【发布时间】:2015-02-24 17:03:55
【问题描述】:
更新:已解决!发布解决方案作为我自己的答案。两天后我可以接受。
一个小故事
过去几天我一直在追查这个兔子洞,而我的问题在那段时间里发生了巨大的变化。最初,我认为Spring Boot 有问题,因为它无法解析我的@Configuration 注释类之一。通过调试,我确定 Spring 正在所有正确的位置寻找我的 JAR 绑定依赖项之一,但在尝试从 JAR 加载类时却出现了 FileNotFoundException。
我被这个吓坏了,因为有问题的 JAR 在类路径上是可以验证的。我可以在应用程序启动期间打印出类路径,并看到我的 JAR 在里面生活得又好又舒适。
所以我简化了。并简化。最终,我将事情归结为一个包含两个 Java 源文件的项目,以及一个很小的占位符 JAR 拉到 Maven。这个JAR 只包含一个文件:tiny/jar/BaseTest.class。
这非常有效。从那里,我在这个小项目上交换了依赖JAR。 . .并且启动失败。所以我比较了JARs,发现有些奇怪。
实现
虽然我的小 JAR 包含以下文件夹层次结构:
tiny/jar/BaseTest.class
较大的JAR 看起来像:
WEB-INF/classes/com/company/...
这个WEB-INF/classes 前缀是杀死Spring Boot 类加载器的毒药。它希望从根目录开始查找类:com/company/... -- 不允许使用前缀。
我相信 Maven 的依赖管理在这里做了一些棘手的事情。当我的JAR 使用clean install 目标创建时,它内部有com/company/... 根。如果我手动将此版本的 JAR 复制到我的服务器 WEB-INF/lib 文件夹中,一切正常、识别并启动。
但是当使用 Maven 引入依赖项时,WEB-INF/classes 会在我的文件夹层次结构中添加前缀,从而破坏了所有内容。
问题
有谁知道如何防止 Maven 更改我的 JAR 的目录结构? JAR 是 100% 正确的,直到 Maven 将其作为依赖项引入,然后突然出现 WEB-INF/classes 前缀。
这里是三个POM 文件供参考。我已经删除了大量依赖项,但为了便于阅读,其他所有内容都保持不变。
小罐子 POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>tiny</groupId>
<artifactId>jar</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<name>jar</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
大罐 POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>company-foundation</artifactId>
<version>0.7.0-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-webflow</artifactId>
<version>2.4.0.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin> <!-- Sonar -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.5</version>
</plugin>
</plugins>
</build>
<repositories>
<!-- To use snapshots, you must also use the Sonatype Snapshots respository -->
<repository>
<id>sonatype-snapshots</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
项目 POM
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>dependency-issue</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<name>jar-dependency-issue</name>
<description>Barebones Spring Boot project used to demonstrate a JAR loading issue.</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.JarDependencyIssueApplication</start-class>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- To run on a separate server, we need to mark tomcat starter as provided. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--
<dependency>
<groupId>com.company</groupId>
<artifactId>company-foundation</artifactId>
<version>0.7.0-SNAPSHOT</version>
</dependency>
-->
<dependency>
<groupId>tiny</groupId>
<artifactId>jar</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
【问题讨论】:
-
那么.. 如果您运行“mvn package”,现在您的“大罐子”里面会是什么?我不太清楚这里可能发生了什么——该项目的 pom 是否曾经指定过战争包装?可能有人将那场战争重命名为 jar 吗?如果“mvn package”当前生成的内容在您检查时看起来是正确的,那么也许您可以执行“mvn install”来替换之前生成的不正确的工件。只是一个想法..
-
使用 Maven 打包时,“大 jar”包含四个文件夹:
templates/、META-INF/、config/和com/,这是完美的。当我将它作为 maven 依赖项引入第二个项目时,一切都会中断。我需要 Maven 依赖项在com/之前没有前缀/WEB-INF/classes--- 除了我之外没有人现在正在接触这个项目,但最终“大”依赖项将成为许多项目的基础。你知道如何防止 Maven 将/WEB-INF/classes文件夹结构添加到以前只包含上面列出的四个文件夹的JAR吗? -
好的。听起来您只需要将您的主要“Project POM”从存储库中获取的那个替换为您现在可以使用“mvn package”正确构建的那个。我在想,如果您只是针对“big jar”项目发出“mvn install”,您将用现在应该满足您需求的工件替换错误生成的工件。有意义吗?
-
在这个过程中,我已经完成了几十次我的包裹的
clean install。我可以查看我的.m2文件夹,其中的JAR是正确的。在将 JAR 依赖项拉入我的子项目之前,它没有问题。 -
之前在 Maven 中看到过一些奇怪的行为,但这不是其中之一(添加 /WEB-INF/classes)。
标签: maven-3 spring-boot