无法自动装配 MapStruct 映射器

问题描述 投票:0回答:6

我正在关注这个关于部分更新的教程。按照指示,我创建了带有适当注释的映射器接口。

这是映射器

@Mapper(componentModel = "spring")
public interface UserEntityMapper {
  
  @Mapping(source = "password", target = "password")
  @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE)
  void updatePasswordFromDTO(PasswordResetRequest dto, @MappingTarget User entity);
}

根据教程,

@Mapper(componentModel = "spring")
生成映射器作为Spring bean,可以通过
@Autowired
检索。

但是当我尝试在服务层中做同样的事情时

class

@Service
@Transactional
public class AccountServiceImpl implements IAccountService {
  ...
  @Autowired
  private UserEntityMapper userMapper;
  ...
}

我收到此错误,我的应用程序无法启动。

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

Description:

Field userMapper in com.application.services.AccountServiceImpl required a bean of type 'com.application.mappers.UserEntityMapper' 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.application.mappers.UserEntityMapper' in your configuration.

最后,这是我的项目的

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 https://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.5.5</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myproject</groupId>
    <artifactId>myproject</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>authentication-template</name>
    <description>Description</description>
    <properties>
        <java.version>11</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>1.4.2.Final</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

我也尝试了这些不同的解决方案,但结果相同。

  1. @Som 的回答
  2. @Gunnar
  3. 的回答

编辑1

这是

@SpringBootApplication
文件。

@SpringBootApplication
@PropertySources(value = {
  @PropertySource("classpath:mail.properties"),
  @PropertySource("classpath:messages.properties"),
  @PropertySource("classpath:security.properties")
})
public class Application {

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

}

编辑2

项目的包结构

请帮忙,谢谢:)

java spring spring-boot spring-rest mapstruct
6个回答
3
投票

如果您提供的 pom.xml 是最新版本,我认为您错过了实际根据您的定义生成 MapStruct 映射器的步骤。您需要将其定义为构建设置的一部分,如此处所述 https://mapstruct.org/documentation/installation/

您需要将该部分添加到构建 - 插件部分

<plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source> <!-- depending on your project -->
                <target>1.8</target> <!-- depending on your project -->
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                    <!-- other annotation processors -->
                </annotationProcessorPaths>
            </configuration>
        </plugin>

如果映射器已成功生成,还请检查您的目标/生成的文件夹

编辑:

运行构建后,请验证您的 Maven 构建输出文件夹 target/ generated-sources 实际上包含一些为 MapStruct 生成的映射器。另请观察您的 Maven 构建日志输出以获取已生成 MapStruct 映射器的提示。

如果没有生成映射器,则构建设置中的某些内容有问题,我们需要仔细查看您的日志输出。

但是如果生成了映射器,您应该检查是否具有 spring 的 @Component 注释,并且它们位于包中,即位于 Springs 的 bean 扫描路径上。


2
投票

添加到插件:

 <compilerArgs>
      <compilerArg>
             -Amapstruct.defaultComponentModel=spring
      </compilerArg>
 </compilerArgs>

1
投票

我有如下的依赖关系,一切都很好。

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.4.2.Final</version>
</dependency>

以及部分插件。


 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                      <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>1.4.2.Final</version>
                      </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

0
投票

您可以研究一些建议。首先检查mvn生成的类中是否有@Component。

  • 如果是这样,请检查您的应用程序是否配置为扫描该包。
  • 如果没有,请尝试阅读 MapStruct 文档

0
投票

我能够按照以下步骤完成这项工作,而且我还使用了 lombok & mapstruct 以及 maven

第1步:添加lombok和mapstruct依赖

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${mapstruct.version}</version>
        </dependency>

第2步:由于mapstruct和lombok都是基于注解处理的。在maven构建插件部分添加配置,如果使用IntelliJ IDEA,则不需要此步骤,通过在IDE设置中启用注释处理。

         <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass></mainClass> <!-- FQN of class with main method
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${lombok.version}</version>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${mapstruct.version}</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>

第3步:Mapper类应该使用@Mapper注释进行注释

@Mapper(componentModel = "spring")
@Service
public interface PersonMapper {
     // add appropriate mapper methods
}

第3步:更新maven项目并运行

mvn 全新安装

运行应用程序。在目标文件夹中将有由mapstruct生成的PersonMapperImpl.java。


0
投票

我知道,我来晚了。对于延迟回答问题表示歉意。让我们深入了解 MapStruct 的配置。

实际问题在于配置。我按照以下步骤成功使用 Spring Boot 配置 MapStruct

  1. 首先在

    mapstruct
    中添加
    pom.xml
    依赖。

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
        <scope>provided</scope> <!-- Required -->
    </dependency>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>1.5.5.Final</version>
    </dependency>
    

    注意: 确保将

    <scope>provided</scope>
    设置为
    lombok
    。没有那个
    @Builder
    对我来说就不起作用。

  2. 由于

    mapstruct
    需要注释处理,所以我们需要将插件添加到我们的
    pom.xml
    中。

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.11.0</version>
        <configuration>
            <annotationProcessorPaths>
                <path>
                    <groupId>org.mapstruct</groupId>
                    <artifactId>mapstruct-processor</artifactId>
                    <version>1.5.5.Final</version>
                </path>
                <path>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok-mapstruct-binding</artifactId>
                    <version>0.2.0</version>
                </path>
                <path>
                    <groupId>org.projectlombok</groupId>
                    <artifactId>lombok</artifactId>
                </path>
            </annotationProcessorPaths>
        </configuration>
    </plugin>
    

    注意:

    lombok-mapstruct-binding
    Lombok
    Mapstruct
    所必需的,以便他们能够合作。

  3. 确保您的 IDE 中启用了注释处理。您可以检查这些链接以获取 IntelliJ IdeaEclipse/STS

  4. 完成后,您可以创建

    mapper interface

    import static org.mapstruct.MappingConstants.ComponentModel.SPRING;
    
    @Mapper(componentModel = SPRING)
    public interface UserMapper {
      UserModel dtoToModel(UserDTO userDto);
    }
    
  5. 那么

    mapper
    就可以轻松
    @Autowired

    @Service
    public class UserService {
    
        private final UserMapper userMapper;
    
        @Autowired
        public UserService(UserMapper userMapper) {
            this.userMapper= userMapper;
        }
    
        // Business logic
    }
    

我希望这会有所帮助。谢谢和问候。

© www.soinside.com 2019 - 2024. All rights reserved.