【问题标题】:Package not found (Multi-module spring project)找不到包(多模块spring项目)
【发布时间】:2019-01-11 11:17:07
【问题描述】:

我使用Spring Initializr创建了两个模块:

api(即 Spring Web)

db(即 Spring Data MongoDB)

我已将它们放在同一个项目中,在某种程度上它们现在是子模块。

在创建测试之前,我可以 mvn clean install 使用 BUILD SUCCESS 消息。没问题。

但是,如果我尝试创建一个测试(甚至在 ma​​in 结构中的控制器中使用它),它使用 db 模块存储库类,以获取来自 MongoDB 的数据,mvn clean install 将指责包不存在,尽管 IntelliJ 可以识别和索引它并且文件存在。

结构是:

api
\- src/main/java
  \- com.example.api.controllers
    \- UserController.java
\- src/test/java
  \- com.example.api.controllers
    \- UserControllerTest.java
db
\- src/main/java
  \- com.example.db.repositories
    \- UserRepository.java
model
\- src/main/java
  \- com.example.model
    \- User.java

ApiApplication.java

package com.example.api;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@SpringBootApplication
public class ApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }

}

UserController.java

package com.example.api.controllers;

import com.example.api.Constants;
import com.example.db.repositories.UserRepository;
import com.example.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @Autowired
    private UserRepository userRepository;

    @GetMapping(Constants.V1 + "user")
    public User getUser() {
        User user = new User("John");
        userRepository.save(user);
        return user;
    }
}

现在,如果我运行 mvn clean install,我将收到 maven 错误消息 package com.example.db.repositories does not exist

Module db是模块api中的依赖,api模块设置为在db之后编译父母的pom。

父级 - pom.xml

<?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.example</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>model</module>
        <module>db</module>
        <module>api</module>
    </modules>

</project>

db - pom.xml

<?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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>db</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>model</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

</project>

api - pom.xml

<?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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>LATEST</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>api</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.example</groupId>
            <artifactId>db</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

如何让maven看到这个包?

找到包后出现新错误

2019-01-14 19:16:55.060  WARN 31104 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'userController': Unsatisfied dependency expressed through field 'userRepository'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.example.db.repositories.UserRepository' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
2019-01-14 19:16:55.066  INFO 31104 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2019-01-14 19:16:55.087  INFO 31104 --- [           main] ConditionEvaluationReportLoggingListener : 

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-01-14 19:16:55.224 ERROR 31104 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field userRepository in com.example.api.controllers.UserController required a bean of type 'com.example.db.repositories.UserRepository' that could not be found.

The injection point has the following annotations:
        - @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.example.db.repositories.UserRepository' in your configuration.

【问题讨论】:

    标签: java spring maven


    【解决方案1】:

    Springboot 自动发现只会从您的配置类下降。你的申请在

    com.example.api
    

    但是仓库在

    com.example.db
    

    要么添加搜索路径以自动发现 .db,要么将您的应用程序类移至 com.example 或将 db 代码移至 com.example.api

    选项 1

    @ComponentScan(“com.example”)
    @SpringBootApplication
    public class ExampleApplication  {
    

    选项 2

    @ComponentScan({"com.example.api","com.example.db"})
    @SpringBootApplication
    public class ExampleApplication {
    

    你也可以在SpringbootApplication注解中添加scanBasePackages属性达到同样的效果。

    @SpringBootApplication(scanBasePackages= {"com.example.api","com.example.db"})
    public class ExampleApplication {
    

    在此处查看文档https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/SpringBootApplication.html#scanBasePackages--

    【讨论】:

    • 将它们作为两个独立的模块是我的主要目标。那么,我怎么能“也添加一个搜索路径来自动发现 .db”?
    • 它与 Maven 模块无关。它关于包裹。自动发现将搜索 api 下面的 java 包。我会为你查找注解参数。
    • 所以,你的意思是,即使像现在这样将它们作为两个单独的模块,并且我将Main类向上移动一个包,它也能找到.db?你正在寻找的注释会这样做,然后阻止我移动它?
    • 是的。它的组件扫描。这个是包含在SpringbootApplication中的,你可以设置一个packages参数,带有一个packages数组来扫描组件。它默认是应用程序类的包(Configuration,也包含在SpringbootApplication中)
    【解决方案2】:

    您正在(重新)将 db 打包为 Spring 启动“应用程序”,而不是使用 spring-boot-maven-plugin 的库:

    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    

    jar 被重新打包,因此在 BOOT-INF 文件夹中添加了com.example.db.repositories 包(及其类)。这会导致编译失败。

    只需从db/pom.xml 中删除&lt;plugin&gt;..&lt;/plugin&gt; 部分。这将创建一个可以在api 模块中导入的常规 jar。

    注意:我假设api 具有Main 类并将打包为启动应用程序。

    【讨论】:

    • 我已按要求完成,现在收到一个新错误。你知道为什么我现在有这个消息吗? Autowired 注释不应该照顾 Bean 吗?我已经编辑了帖子以显示它。
    • 你的 Main 类的包是什么(我猜在 api 模块中)?
    • 哦,我的错,错过了。所以问题是你的SpringBootApplication类在“组件扫描”期间找不到repositories包。默认情况下,组件扫描从主类的包开始查找子包中的类。所以主类必须在com.example,这样才能在com.examplecom.example.apicom.example.db等下找到类。
    • 另一种选择是在注解SpringBootApplication 中显式配置scanBasePackages:`@SpringBootApplication(scanBasePackages= { "com.example.db", "com.example.ab" })。我更喜欢前一种方法。
    • 是的,如果您将第一类软件包向上移动,它会起作用。由于类加载器是相同的,所以不同模块中具有相同限定名的包基本相同。
    【解决方案3】:

    确实,API 必须看到 DB 类。

    确保:

    1. 父?项目是包装类型pom (&lt;packaging&gt;pom&lt;/packaging&gt;)
    2. 如果?api的依赖与?db的版本相同

    【讨论】:

    • 可能是另一个进程将 .jar 锁定在 .m2/repository 中。您可以尝试将.m2/repository-folder 重命名为.m2/repository-old 并重试吗?
    • 也试过了,没有成功。 :(
    猜你喜欢
    • 2019-07-05
    • 2016-01-12
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    • 2022-01-24
    • 2018-10-07
    相关资源
    最近更新 更多