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

15

我正在尝试使用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'
}

有人可以帮忙吗?

谢谢,

Amar

3个回答

4

排除传递性依赖并调整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'
    }

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

3
根据Jigsaw规范

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

这被称为@Andy在这里的答案中所述的“分割包”。解决方法是取消这些包的分割,并确保从您的模块中包含的包jcl.over.slf4jcommons.logging只通过一个模块访问。

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


0

这样的问题会出现在多个库中,比如Apache Mina(sshd-core),其中sshd-core和sshd-common之间存在分裂。类似的情况也会发生在Springfox Swagger 2中,你可能会遇到类似的分裂包问题:“模块XXX从springfox.core和springfox.spi中都读取了springfox.documentation服务包。

经过多种方式的分析,我找到了一种适用于所有情况的解决方案。

这个想法是将有问题的库重新打包成单个jar文件,并将其安装到公司(或本地)仓库中。如果你有公司范围的nexus,你可以安装它,否则在运行整个构建之前,你可以手动将这样的库安装到本地maven仓库中。

虽然这看起来像是一个过度杀伤力的方法,而且不容易实现,但事实上它非常简单。

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

对于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>

请注意两件事情。首先是汇编插件的配置参数<appendAssemblyId>false</appendAssemblyId>。其次是排除所有瞬态依赖项,以便它们不会被包含在最终包中。
准备好pom.xml后,您可以进入新模块目录并运行clean installclean package,以创建一个包含所有依赖项编译为单个jar的软件包。该jar文件将位于您的目标文件夹下。这样,您将创建一个名为springfox-all-3.0.0.jar的文件(其中包含单个模块中的所有springfox代码)。
现在,您可以将此软件包安装到本地repo中,或者更好地将其部署到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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接