java 9模块从A和B读取包X

Posted

技术标签:

【中文标题】java 9模块从A和B读取包X【英文标题】:java 9 module reads package X from A and B 【发布时间】:2017-11-11 19:28:43 【问题描述】:

我正在尝试将 spring boot 与 java 9 和 gradle 一起使用。 我无法运行我的简单代码,出现以下错误:-

Information:java: Errors occurred while compiling module 'Java9Gradle_main'
Information:javac 9-ea was used to compile java sources
Information:6/9/2017 10:40 PM - Compilation completed with 65 errors and 0 warnings in 15s 200ms
Error:java: module  reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module  reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter.web reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter.web reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.autoconfigure reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.autoconfigure reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter.logging reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter.logging reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.core reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.core reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module snakeyaml reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module snakeyaml reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter.tomcat reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter.tomcat reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module hibernate.validator reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module hibernate.validator reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module jackson.databind reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module jackson.databind reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.web reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.web reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.webmvc reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.webmvc reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.context reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.context reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module logback.classic reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module logback.classic reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module jcl.over.slf4j reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module jcl.over.slf4j reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module jul.to.slf4j reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module jul.to.slf4j reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module log4j.over.slf4j reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module log4j.over.slf4j reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module commons.logging reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module commons.logging reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module tomcat.embed.core reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module tomcat.embed.core reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module tomcat.embed.el reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module tomcat.embed.el reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module tomcat.embed.websocket reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module tomcat.embed.websocket reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module validation.api reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module validation.api reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module jboss.logging reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module jboss.logging reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module classmate reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module classmate reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module jackson.annotations reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module jackson.annotations reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module jackson.core reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module jackson.core reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.aop reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.aop reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.beans reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.beans reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.expression reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.expression reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module logback.core reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module logback.core reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module slf4j.api reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module slf4j.api reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot.starter reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging
Error:java: module spring.boot reads package org.apache.commons.logging.impl from both jcl.over.slf4j and commons.logging
D:\project\Java9Gradle\src\main\java\module-info.java
Error:(1, 1) java: module Java9Gradle.main reads package org.apache.commons.logging from both jcl.over.slf4j and commons.logging

我的依赖文件和 module-info.java 文件非常简单。

module Java9Gradle.main 
    requires spring.boot;



group 'Java9Gradle'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.9

repositories 
    mavenCentral()


dependencies 
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter
    compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: '1.5.3.RELEASE'
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '1.5.3.RELEASE'
    testCompile group: 'junit', name: 'junit', version: '4.12'

有人可以帮忙吗?

谢谢,

阿马尔

【问题讨论】:

【参考方案1】:

此类问题发生在多个库中,例如 Apache Mina (sshd-core),其中 sshd-core 和 sshd-common 之间存在拆分。与 Springfox Swagger 2 类似,您可以在其中遇到类似的拆分包问题:“Module XXX 从 springfox.core 和 springfox.spi 读取包 springfox.documentation 服务。

在分析了如何克服它的多种方法后,我找到了一种适用于所有情况的解决方案。

这个想法是将有问题的库重新打包到单个 jar 中,然后将它们安装到您的公司(或本地存储库)中。如果您有公司范围的 nexus,则可以安装它,否则在运行整个构建之前,您可以手动将此类库安装到本地 maven 存储库。

虽然这些看起来有点矫枉过正,而且不容易做到,但实际上很容易。

您需要在主项目中创建新的 maven 模块(如果您没有运行多模块项目,则需要创建单独的 maven 项目)。然后将引入包拆分的依赖项添加到您的 pom.xml 并配置 maven 程序集插件以重新打包它们。

对于 spring-fox,这将是

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <appendAssemblyId>false</appendAssemblyId>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

<dependencies>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger2</artifactId>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-core</artifactId>
        <version>$io.springfox.version</version>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-swagger-ui</artifactId>
        <version>$io.springfox.version</version>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-spring-webmvc</artifactId>
        <version>$io.springfox.version</version>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-schema</artifactId>
        <version>$io.springfox.version</version>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-spring-web</artifactId>
        <version>$io.springfox.version</version>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>io.springfox</groupId>
        <artifactId>springfox-spi</artifactId>
        <exclusions>
            <exclusion>
                <groupId>*</groupId>
                <artifactId>*</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

</dependencies>

请注意两件事。首先&lt;appendAssemblyId&gt;false&lt;/appendAssemblyId&gt; 作为程序集插件的配置参数。第二次排除所有瞬态依赖,使它们不会被包含到最终包中。

准备好 pom.xml 后,您可以转到新模块目录并运行 clean installclean package 以创建一个包,并将所有依赖项编译到单个 jar 中。 jar 将位于您的目标文件夹下。这样您将创建您命名的文件,例如springfox-all-3.0.0.jar(包含单个模块中的所有springfox代码)。

现在您可以将此软件包安装到本地仓库中,或者更好地将其部署到您的 nexus,例如使用以下命令

mvn deploy:deploy-file -Dversion=3.0.0-SNAPSHOT -Durl=http://nexus.youc.company.net/nexus/content/repositories/yourRepoId -Dfile=springfox-all-3.0.0.jar -DgroupId=patched.io.springfox -DrepositoryId=yourRepoId -DartifactId=springfox-all

现在在你的 pom.xml 文件和你的 module-info.java 中使用这个依赖而不是你项目中的单个依赖集

module com.acme.your.module 

//  requires springfox.spring.web;
//  requires springfox.swagger2;
//  requires springfox.core;
//  requires springfox.spi;
  requires springfox.all;

【讨论】:

【参考方案2】:

根据Jigsaw specs

无干扰——Java 编译器、虚拟机和运行时 系统必须确保包含同名包的模块 不要互相干扰。如果两个不同的模块包含 那么,从每个模块的角度来看,同名的包, 该包中的所有类型和成员仅由该包定义 模块。一个模块中该包中的代码不能访问 包私有类型或其他模块中该包中的成员。

这在@Andy here 的回答中被称为拆分包。因此解决方案是解开这些包,并确保您的模块jcl.over.slf4jcommons.logging 中包含的包只能通过一个模块访问。


您可以分析 spring-boot-starter:1.5.3.RELEASEspring-boot-starter-web:1.5.3.RELEASE 这两个依赖项,以确保您的项目中包含这两个模块中的任何一个。

【讨论】:

【参考方案3】:

排除传递依赖使其工作并调整module-info.java!!!

compile("org.springframework.boot:spring-boot-starter:1.5.3.RELEASE") 
        exclude group: 'commons-logging', module: 'commons-logging'
    
    compile("org.springframework.boot:spring-boot-starter-web:1.5.3.RELEASE")
        exclude group: 'commons-logging', module: 'commons-logging'
    

【讨论】:

module-info.java 文件需要做哪些调整?

以上是关于java 9模块从A和B读取包X的主要内容,如果未能解决你的问题,请参考以下文章

如何解决java9中的模块读取包错误

9_模块_包导入

Python_9 py文件导入和路径处理

电子学会青少年软件编程 Python编程等级考试三级真题解析(选择题)2020年9月B卷

java如何将引用了第三方模块的A项目打包成jar包后,在B项目中引用A项目打包成的jar包?

python 解决粘包现象(struct模块)