🎯 学习目标
通过本篇教程,你将学会:
- 搭建 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(推荐)
- 访问 start.spring.io/
- 配置项目参数:
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:
- 右键项目 → Open Module Settings
- Sources → Add Content Root
- 选择
target/generated-sources/annotations
- 标记为 Sources
Eclipse:
- 项目属性 → Java Build Path
- Source → Add Folder
- 选择
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: 确保以下配置:
- 包扫描路径正确:
java
@SpringBootApplication
// 如果映射器不在主类包下,需要指定扫描路径
@ComponentScan(basePackages = {"com.example.atlasmapperdemo"})
public class AtlasMapperDemoApplication {
// ...
}
- 映射器接口配置正确:
java
@Mapper(componentModel = "spring") // 必须指定 componentModel
public interface UserMapper {
// ...
}
🎯 本章小结
通过本章学习,你应该掌握了:
- 环境搭建:JDK 8 + Maven + IDE 的配置
- 项目创建:Spring Boot 项目的标准结构
- 依赖配置:Atlas Mapper 的 Maven 配置
- 注解处理器:编译时代码生成的配置
- 验证方法:如何确认环境配置正确
📖 下一步学习
在下一篇教程中,我们将深入学习:
- Atlas Mapper 的核心注解详解
- 基础映射规则和配置
- 字段映射的各种场景