Atlas Mapper 教程系列 (2/10):环境搭建与项目初始化

🎯 学习目标

通过本篇教程,你将学会:

  • 搭建 Atlas Mapper 开发环境
  • 创建第一个 Atlas Mapper 项目
  • 配置 Maven 构建和注解处理器
  • 验证环境配置是否正确

📋 概念讲解:开发环境要求

技术栈要求

Atlas Mapper 基于以下技术栈开发:

graph TB subgraph "基础环境" A1[JDK 8+] --> A2[Maven 3.6+] A2 --> A3[IDE支持] end subgraph "Spring 技术栈" B1[Spring Framework 5.2+] --> B2[Spring Boot 2.2+] end subgraph "开发工具" C1[IntelliJ IDEA] --> C2[Eclipse] C2 --> C3[VS Code] end A3 --> B1 B2 --> C1 style A1 fill:#e8f5e8 style B1 fill:#e3f2fd style C1 fill:#fff3e0

环境检查清单

组件 最低版本 推荐版本 检查命令
JDK 1.8 1.8.0_271+ java -version
Maven 3.6.0 3.8.0+ mvn -version
IDE - IntelliJ IDEA 2020+ -

🔧 实现步骤:环境搭建详细指南

步骤 1:验证 Java 环境

bash 复制代码
# 检查 Java 版本
java -version

# 期望输出类似:
# java version "1.8.0_271"
# Java(TM) SE Runtime Environment (build 1.8.0_271-b09)
# Java HotSpot(TM) 64-Bit Server VM (build 25.271-b09, mixed mode)

# 检查 JAVA_HOME 环境变量
echo $JAVA_HOME
# 期望输出:/usr/lib/jvm/java-8-openjdk-amd64 (Linux)
# 或:C:\Program Files\Java\jdk1.8.0_271 (Windows)

步骤 2:验证 Maven 环境

bash 复制代码
# 检查 Maven 版本
mvn -version

# 期望输出类似:
# Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)
# Maven home: /usr/share/maven
# Java version: 1.8.0_271, vendor: Private Build
# Java home: /usr/lib/jvm/java-8-openjdk-amd64/jre

步骤 3:创建 Spring Boot 项目

方式一:使用 Spring Initializr(推荐)

  1. 访问 start.spring.io/
  2. 配置项目参数:
yaml 复制代码
项目配置:
  Project: Maven Project
  Language: Java
  Spring Boot: 2.2.13
  
项目元数据:
  Group: com.example
  Artifact: atlas-mapper-demo
  Name: atlas-mapper-demo
  Description: Atlas Mapper Demo Project
  Package name: com.example.atlasmapperdemo
  Packaging: Jar
  Java: 8

依赖选择:
  - Spring Web
  - Spring Boot DevTools
  - Lombok (可选)

方式二:手动创建项目结构

bash 复制代码
# 创建项目目录
mkdir atlas-mapper-demo
cd atlas-mapper-demo

# 创建标准 Maven 目录结构
mkdir -p src/main/java/com/example/atlasmapperdemo
mkdir -p src/main/resources
mkdir -p src/test/java/com/example/atlasmapperdemo

步骤 4:配置 Maven POM 文件

创建 pom.xml 文件:

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>atlas-mapper-demo</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <name>Atlas Mapper Demo</name>
    <description>Atlas Mapper 框架演示项目</description>

    <!-- Spring Boot 父项目 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.13.RELEASE</version>
        <relativePath/>
    </parent>

    <!-- 属性配置 -->
    <properties>
        <java.version>1.8</java.version>
        <atlas-mapper.version>1.0.0-SNAPSHOT</atlas-mapper.version>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- 依赖管理 -->
    <dependencies>
        <!-- Spring Boot Starter Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Atlas Mapper Spring Boot Starter -->
        <dependency>
            <groupId>io.github.nemoob</groupId>
            <artifactId>atlas-mapper-spring-boot-starter</artifactId>
            <version>${atlas-mapper.version}</version>
        </dependency>

        <!-- 开发工具 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!-- 构建配置 -->
    <build>
        <plugins>
            <!-- Spring Boot Maven 插件 -->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <!-- Maven 编译插件 - 关键配置! -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                    <encoding>UTF-8</encoding>
                    
                    <!-- 🔥 注解处理器配置 - 核心配置 -->
                    <annotationProcessorPaths>
                        <path>
                            <groupId>io.github.nemoob</groupId>
                            <artifactId>atlas-mapper-processor</artifactId>
                            <version>${atlas-mapper.version}</version>
                        </path>
                    </annotationProcessorPaths>
                    
                    <!-- 编译参数 -->
                    <compilerArgs>
                        <arg>-Amapstruct.defaultComponentModel=spring</arg>
                        <arg>-Amapstruct.unmappedTargetPolicy=IGNORE</arg>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

💻 示例代码:创建第一个映射器

创建实体类

java 复制代码
// src/main/java/com/example/atlasmapperdemo/entity/User.java
package com.example.atlasmapperdemo.entity;

import java.time.LocalDateTime;

/**
 * 用户实体类
 */
public class User {
    private Long id;
    private String firstName;
    private String lastName;
    private String email;
    private String phoneNumber;
    private LocalDateTime createdAt;
    private Boolean active;

    // 构造方法
    public User() {}

    public User(Long id, String firstName, String lastName, String email) {
        this.id = id;
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.createdAt = LocalDateTime.now();
        this.active = true;
    }

    // Getter 和 Setter 方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getFirstName() { return firstName; }
    public void setFirstName(String firstName) { this.firstName = firstName; }

    public String getLastName() { return lastName; }
    public void setLastName(String lastName) { this.lastName = lastName; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public String getPhoneNumber() { return phoneNumber; }
    public void setPhoneNumber(String phoneNumber) { this.phoneNumber = phoneNumber; }

    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }

    public Boolean getActive() { return active; }
    public void setActive(Boolean active) { this.active = active; }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", firstName='" + firstName + '\'' +
                ", lastName='" + lastName + '\'' +
                ", email='" + email + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                ", createdAt=" + createdAt +
                ", active=" + active +
                '}';
    }
}

创建 DTO 类

java 复制代码
// src/main/java/com/example/atlasmapperdemo/dto/UserDto.java
package com.example.atlasmapperdemo.dto;

/**
 * 用户 DTO 类
 */
public class UserDto {
    private Long id;
    private String fullName;        // 组合字段
    private String email;
    private String phone;           // 字段名不同
    private String createTime;      // 类型不同
    private String status;          // 字段名和类型都不同

    // 构造方法
    public UserDto() {}

    // Getter 和 Setter 方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }

    public String getFullName() { return fullName; }
    public void setFullName(String fullName) { this.fullName = fullName; }

    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }

    public String getPhone() { return phone; }
    public void setPhone(String phone) { this.phone = phone; }

    public String getCreateTime() { return createTime; }
    public void setCreateTime(String createTime) { this.createTime = createTime; }

    public String getStatus() { return status; }
    public void setStatus(String status) { this.status = status; }

    @Override
    public String toString() {
        return "UserDto{" +
                "id=" + id +
                ", fullName='" + fullName + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                ", createTime='" + createTime + '\'' +
                ", status='" + status + '\'' +
                '}';
    }
}

创建映射器接口

java 复制代码
// src/main/java/com/example/atlasmapperdemo/mapper/UserMapper.java
package com.example.atlasmapperdemo.mapper;

import com.example.atlasmapperdemo.dto.UserDto;
import com.example.atlasmapperdemo.entity.User;
import io.github.nemoob.atlas.mapper.Mapper;
import io.github.nemoob.atlas.mapper.Mapping;

import java.util.List;

/**
 * 用户映射器接口
 * 
 * 🔥 关键点:
 * 1. 使用 @Mapper 注解标记接口
 * 2. componentModel = "spring" 让生成的实现类成为 Spring Bean
 * 3. 使用 @Mapping 注解处理字段映射
 */
@Mapper(componentModel = "spring")
public interface UserMapper {

    /**
     * 将 User 实体转换为 UserDto
     * 
     * 映射规则:
     * - id -> id (自动映射,字段名和类型相同)
     * - email -> email (自动映射)
     * - phoneNumber -> phone (字段名映射)
     * - createdAt -> createTime (字段名和类型映射)
     * - firstName + lastName -> fullName (表达式映射)
     * - active -> status (自定义方法映射)
     */
    @Mapping(target = "phone", source = "phoneNumber")
    @Mapping(target = "createTime", source = "createdAt", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "fullName", 
             expression = "java(user.getFirstName() + \" \" + user.getLastName())")
    @Mapping(target = "status", source = "active", qualifiedByName = "mapActiveToStatus")
    UserDto toDto(User user);

    /**
     * 批量转换
     */
    List<UserDto> toDtoList(List<User> users);

    /**
     * 反向映射:UserDto -> User
     */
    @Mapping(target = "phoneNumber", source = "phone")
    @Mapping(target = "createdAt", source = "createTime", dateFormat = "yyyy-MM-dd HH:mm:ss")
    @Mapping(target = "firstName", ignore = true)  // 需要特殊处理
    @Mapping(target = "lastName", ignore = true)   // 需要特殊处理
    @Mapping(target = "active", source = "status", qualifiedByName = "mapStatusToActive")
    User toEntity(UserDto dto);

    /**
     * 自定义映射方法:Boolean -> String
     */
    @org.mapstruct.Named("mapActiveToStatus")
    default String mapActiveToStatus(Boolean active) {
        if (active == null) {
            return "未知";
        }
        return active ? "激活" : "禁用";
    }

    /**
     * 自定义映射方法:String -> Boolean
     */
    @org.mapstruct.Named("mapStatusToActive")
    default Boolean mapStatusToActive(String status) {
        if (status == null) {
            return null;
        }
        return "激活".equals(status);
    }
}

创建主应用类

java 复制代码
// src/main/java/com/example/atlasmapperdemo/AtlasMapperDemoApplication.java
package com.example.atlasmapperdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Atlas Mapper 演示应用主类
 */
@SpringBootApplication
public class AtlasMapperDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(AtlasMapperDemoApplication.class, args);
        System.out.println("🚀 Atlas Mapper Demo 应用启动成功!");
        System.out.println("📖 访问 http://localhost:8080/api/users/demo 查看演示效果");
    }
}

创建测试控制器

java 复制代码
// src/main/java/com/example/atlasmapperdemo/controller/UserController.java
package com.example.atlasmapperdemo.controller;

import com.example.atlasmapperdemo.dto.UserDto;
import com.example.atlasmapperdemo.entity.User;
import com.example.atlasmapperdemo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 用户控制器 - 演示 Atlas Mapper 的使用
 */
@RestController
@RequestMapping("/api/users")
public class UserController {

    @Autowired
    private UserMapper userMapper; // 🔥 自动注入生成的映射器实现

    /**
     * 演示单个对象映射
     */
    @GetMapping("/demo")
    public UserDto getDemoUser() {
        // 创建测试用户
        User user = new User();
        user.setId(1L);
        user.setFirstName("张");
        user.setLastName("三");
        user.setEmail("zhangsan@example.com");
        user.setPhoneNumber("13800138000");
        user.setCreatedAt(LocalDateTime.now());
        user.setActive(true);

        // 🎯 使用 Atlas Mapper 进行映射
        UserDto dto = userMapper.toDto(user);
        
        System.out.println("原始用户: " + user);
        System.out.println("映射结果: " + dto);
        
        return dto;
    }

    /**
     * 演示批量映射
     */
    @GetMapping("/demo-list")
    public List<UserDto> getDemoUserList() {
        // 创建测试用户列表
        List<User> users = Arrays.asList(
            createUser(1L, "张", "三", "zhangsan@example.com", true),
            createUser(2L, "李", "四", "lisi@example.com", false),
            createUser(3L, "王", "五", "wangwu@example.com", true)
        );

        // 🎯 批量映射
        List<UserDto> dtos = userMapper.toDtoList(users);
        
        System.out.println("批量映射完成,共处理 " + dtos.size() + " 个用户");
        
        return dtos;
    }

    /**
     * 演示反向映射
     */
    @PostMapping("/demo-reverse")
    public User createUserFromDto(@RequestBody UserDto dto) {
        // 🎯 反向映射:DTO -> Entity
        User user = userMapper.toEntity(dto);
        
        // 手动处理无法自动映射的字段
        if (dto.getFullName() != null && dto.getFullName().contains(" ")) {
            String[] names = dto.getFullName().split(" ", 2);
            user.setFirstName(names[0]);
            user.setLastName(names.length > 1 ? names[1] : "");
        }
        
        System.out.println("反向映射结果: " + user);
        
        return user;
    }

    /**
     * 辅助方法:创建测试用户
     */
    private User createUser(Long id, String firstName, String lastName, String email, Boolean active) {
        User user = new User();
        user.setId(id);
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setEmail(email);
        user.setPhoneNumber("138" + String.format("%08d", id));
        user.setCreatedAt(LocalDateTime.now().minusDays(id));
        user.setActive(active);
        return user;
    }
}

🎬 效果演示:验证环境配置

步骤 1:编译项目

bash 复制代码
# 清理并编译项目
mvn clean compile

# 期望看到类似输出:
# [INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ atlas-mapper-demo ---
# [INFO] Changes detected - recompiling the module!
# [INFO] Compiling 5 source files to /path/to/target/classes
# [INFO] Atlas Mapper processor is running...
# [INFO] Processing @Mapper interface: UserMapper
# [INFO] Generated implementation: UserMapperImpl
# [INFO] BUILD SUCCESS

步骤 2:检查生成的代码

编译成功后,检查生成的实现类:

bash 复制代码
# 查看生成的代码目录
ls -la target/generated-sources/annotations/com/example/atlasmapperdemo/mapper/

# 应该看到生成的文件:
# UserMapperImpl.java

生成的 UserMapperImpl.java 内容示例:

java 复制代码
// target/generated-sources/annotations/.../UserMapperImpl.java
@Component
public class UserMapperImpl implements UserMapper {

    @Override
    public UserDto toDto(User user) {
        if (user == null) {
            return null;
        }

        UserDto userDto = new UserDto();

        userDto.setPhone(user.getPhoneNumber());
        if (user.getCreatedAt() != null) {
            userDto.setCreateTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                .format(user.getCreatedAt()));
        }
        userDto.setStatus(mapActiveToStatus(user.getActive()));
        userDto.setId(user.getId());
        userDto.setEmail(user.getEmail());
        userDto.setFullName(user.getFirstName() + " " + user.getLastName());

        return userDto;
    }

    // ... 其他方法实现
}

步骤 3:启动应用

bash 复制代码
# 启动 Spring Boot 应用
mvn spring-boot:run

# 期望看到启动日志:
# 🚀 Atlas Mapper Demo 应用启动成功!
# 📖 访问 http://localhost:8080/api/users/demo 查看演示效果

步骤 4:测试映射功能

bash 复制代码
# 测试单个对象映射
curl http://localhost:8080/api/users/demo

# 期望返回:
# {
#   "id": 1,
#   "fullName": "张 三",
#   "email": "zhangsan@example.com",
#   "phone": "13800138000",
#   "createTime": "2025-01-09 15:30:45",
#   "status": "激活"
# }

# 测试批量映射
curl http://localhost:8080/api/users/demo-list

# 期望返回用户列表...

❓ 常见问题

Q1: 编译时提示找不到 Atlas Mapper 依赖?

A: 这是因为 Atlas Mapper 还在开发中,需要先本地安装:

bash 复制代码
# 在 Atlas Mapper 源码目录执行
mvn clean install

# 然后在你的项目中就可以使用了

Q2: IDE 中看不到生成的代码?

A: 需要配置 IDE 识别生成的源码目录:

IntelliJ IDEA:

  1. 右键项目 → Open Module Settings
  2. Sources → Add Content Root
  3. 选择 target/generated-sources/annotations
  4. 标记为 Sources

Eclipse:

  1. 项目属性 → Java Build Path
  2. Source → Add Folder
  3. 选择 target/generated-sources/annotations

Q3: 注解处理器没有运行?

A: 检查以下配置:

xml 复制代码
<!-- 确保 Maven 编译插件配置正确 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <!-- 必须配置注解处理器路径 -->
        <annotationProcessorPaths>
            <path>
                <groupId>io.github.nemoob</groupId>
                <artifactId>atlas-mapper-processor</artifactId>
                <version>1.0.0-SNAPSHOT</version>
            </path>
        </annotationProcessorPaths>
    </configuration>
</plugin>

Q4: Spring Boot 启动时找不到映射器 Bean?

A: 确保以下配置:

  1. 包扫描路径正确
java 复制代码
@SpringBootApplication
// 如果映射器不在主类包下,需要指定扫描路径
@ComponentScan(basePackages = {"com.example.atlasmapperdemo"})
public class AtlasMapperDemoApplication {
    // ...
}
  1. 映射器接口配置正确
java 复制代码
@Mapper(componentModel = "spring") // 必须指定 componentModel
public interface UserMapper {
    // ...
}

🎯 本章小结

通过本章学习,你应该掌握了:

  1. 环境搭建:JDK 8 + Maven + IDE 的配置
  2. 项目创建:Spring Boot 项目的标准结构
  3. 依赖配置:Atlas Mapper 的 Maven 配置
  4. 注解处理器:编译时代码生成的配置
  5. 验证方法:如何确认环境配置正确

📖 下一步学习

在下一篇教程中,我们将深入学习:

  • Atlas Mapper 的核心注解详解
  • 基础映射规则和配置
  • 字段映射的各种场景
相关推荐
杨杨杨大侠2 小时前
Atlas Mapper 教程系列 (1/10):框架概述与设计思路
java·开源·github
椰椰椰耶2 小时前
[Spring Cloud][3]从零开始简单工程搭建实践详解,远程调用
java·数据库·spring cloud
兔子撩架构3 小时前
Akka Cluster的整体应用:系统管理的核心支撑
java·架构
毕设源码-李学长3 小时前
计算机毕业设计java高校多媒体教室管理系统高校多媒体教室综合管理系统高校智能多媒体教室管理平台
java·开发语言·课程设计
AAA修煤气灶刘哥3 小时前
从 Timer 到 XXL-Job,定时任务调度的 “进化史”,看完再也不怕漏跑任务~
java·后端·架构
Funcy3 小时前
XxlJob 源码分析04:admin与executor通讯
java
托比-马奎尔3 小时前
初识SpringBoot
java·spring boot·后端
前行的小黑炭3 小时前
Android :如何提升代码的扩展性,方便复制到其他项目不会粘合太多逻辑,增强你的实战经验。
android·java·kotlin
-凌凌漆-3 小时前
【Qt】【C++】虚析构函数及 virtual ~Base() = default
java·c++·qt