我无法在我的 Spring 项目中添加 mapstruct

I can't add mapstruct in my Spring project

我尝试在我的 Spring 项目中添加 mapstruct 映射器。

我有一个用户实体。我需要在管理面板中显示用户列表。为此,我做了 DTO UserForAdmin、映射器 UserMapper 和其余控制器 AdminRestController。当我尝试获取 UserMapper 时出现错误。

我尝试了两种方式:

  1. Mappers.getMapper(UserMapper.class)

我收到错误

java.lang.ClassNotFoundException: Cannot find implementation for ru.project.mapper.UserMapper

  1. 自动装配

我收到错误

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 2019-07-17 15:47:07.886 ERROR 13652 --- [ restartedMain] o.s.b.d.LoggingFailureAnalysisReporter :

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


Description:

Field userMapper in ru.project.controller.rest.AdminRestController required a bean of type 'ru.project.mapper.UserMapper' 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 'ru.project.mapper.UserMapper' 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 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.6.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>ru.project</groupId>
    <artifactId>project</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>project</name>
    <description>The project is project of resourse for investors.</description>

    <properties>
        <java.version>12</java.version>
        <org.mapstruct.version>1.3.0.Final</org.mapstruct.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-thymeleaf</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>org.postgresql</groupId>
            <artifactId>postgresql</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>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>
        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>2.3.5</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                        <path>
                            <groupId>org.mapstruct</groupId>
                            <artifactId>mapstruct-processor</artifactId>
                            <version>${org.mapstruct.version}</version>
                        </path>                 
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

我的界面 UserMapper:

package ru.project.mapper;

import java.util.List;

import org.mapstruct.Mapper;
import ru.project.domain.User;
import ru.project.dto.UserForAdmin;

@Mapper
//@Mapper(componentModel = "spring")
public interface UserMapper {

    UserForAdmin UserToUserForAdmin(User user);

    List<UserForAdmin> UserListToUserForAdminList(List<User> user);


}

我的 RestController:

package ru.project.controller.rest;

import java.util.List;

import org.mapstruct.factory.Mappers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import ru.project.dto.UserForAdmin;
import ru.project.mapper.UserMapper;
import ru.project.service.UserService;

@RestController
public class AdminRestController {

    @Autowired
    private UserService userService;

    //@Autowired
    //private UserMapper userMapper;

    @GetMapping("/admin/users")
    public List<UserForAdmin> findAllUsers(){

        UserMapper userMapper = Mappers.getMapper(UserMapper.class);

        return userMapper.UserListToUserForAdminList(userService.findAll()); 
    }

}

我想使用 Awtowired。

使用 @Mapper(componentModel = "spring") - 启用 di。 运行 mvn package 命令 - 它创建实现 class。 @Autowired映射器接口和使用。

(java中的方法名首字母要小写)

找不到 ru.project.mapper.UserMapper 的实现,这意味着 UserMapper 必须由某些 class 实现。

如public Class UserMapperImple 实现 UserMapper {XXXXXXX}

然后 Mappers.getMapper("UserMapper") 将获得 UserMapperImple。

考虑在您的配置中定义一个 'ru.project.mapper.UserMapper' 类型的 bean。这意味着 @Mapper 不起作用;我建议你检查 spring-config.xml。 ApplicationContext 可能不会扫描此包。

希望能帮到你:)

你需要使用@Mapper(componentModel="spring")

package ru.project.mapper;

    import java.util.List;

    import org.mapstruct.Mapper;
    import ru.project.domain.User;
    import ru.project.dto.UserForAdmin;

        @Mapper(componentModel = "spring")
        public interface UserMapper {

            UserForAdmin UserToUserForAdmin(User user);

            List<UserForAdmin> UserListToUserForAdminList(List<User> user);

        }

并在下面的 AdminRestController 中使用

@Autowired  
private UserMapper userMapper;

并且我假设 UserUserForAdmin 具有相同的字段名称 在此之后 运行 mvn clean compile 和来源将被生成

使用注释 @Mapper(componentModel = "spring") 的另一种方法是将组件模型作为编译器参数添加到插件中。注释有效,但烦人的事情可能是必须将它添加到您创建的每个映射器中。您添加一次并适用于项目中所有映射器的编译器参数。下面是带有 componentModel 编译器参数的插件定义示例。

<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>${org.mapstruct.version}</version>
                        </path>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>${org.projectlombok.version}</version>
                        </path>
                    </annotationProcessorPaths>
                    <compilerArgs>
                        <arg>-Amapstruct.defaultComponentModel=spring</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

我已经在版本 1.3.0.Final 以及 1.3.1.Final 和 sping boot 2.1.7/8/9

上试过了

有一种简单的解决方法。

在您的映射器 class 处,使用 @Mapper(componentModel = "spring")

和来自终端的 运行 mvn clean install 命令。

或者在 STS/Eclipse 的情况下,转到 Project> 运行 As> maven clean

然后运行 Project> 运行 As> maven install

您的映射器 Impl 将生成!

注意:关于插件

如果您同时使用以下两个依赖项,则无需在 pom.xml 文件中使用插件

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

而且属性会像;

    <properties>
        <java.version>11</java.version>
        <org.mapstruct.version>1.3.1.Final</org.mapstruct.version>
    </properties>