Lombok使用指南
Lombok使用指南
目录
- 什么是Lombok
- 安装与配置
- Lombok的主要注解
- Lombok的优缺点
- 最佳实践
- 常见问题与解决方案
- 兼容性与IDE支持
- 实际应用场景
- 总结
什么是Lombok
Lombok是一个Java库,它通过注解的方式,帮助开发者减少样板代码的编写,如getter、setter、构造方法、equals、hashCode等方法。Lombok在编译时自动生成这些代码,使Java代码更加简洁、易读。
Lombok的工作原理
Lombok通过Java的注解处理器(Annotation Processor)在编译时自动生成代码。当Java编译器编译带有Lombok注解的类时,Lombok的注解处理器会拦截编译过程,分析注解,然后生成相应的代码。这些生成的代码会被编译到最终的class文件中,但在源代码中是不可见的。
为什么需要Lombok
在Java开发中,我们经常需要编写大量的样板代码,例如:
public class User {
private Long id;
private String username;
private String password;
// 构造函数
public User() {}
public User(Long id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
}
// Getter和Setter方法
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
// equals和hashCode方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return Objects.equals(id, user.id) &&
Objects.equals(username, user.username) &&
Objects.equals(password, user.password);
}
@Override
public int hashCode() {
return Objects.hash(id, username, password);
}
// toString方法
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
使用Lombok后,上面的代码可以简化为:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String username;
private String password;
}
这样,我们就减少了大量的样板代码,使代码更加简洁、易读,同时也减少了出错的可能性。
安装与配置
Maven项目安装步骤
- 打开项目的
pom.xml
文件 - 在
<dependencies>
标签内添加以下依赖:<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency>
- 保存文件,Maven会自动下载依赖
- 如果使用IDE(如IntelliJ IDEA),需要安装Lombok插件:
- 打开IDE设置(File > Settings)
- 转到插件市场(Plugins)
- 搜索"Lombok"并安装
- 重启IDE
Gradle项目安装步骤
- 打开项目的
build.gradle
文件 - 在
dependencies
块中添加以下依赖:compileOnly 'org.projectlombok:lombok:1.18.30' annotationProcessor 'org.projectlombok:lombok:1.18.30'
- 保存文件,Gradle会自动下载依赖
- 同样需要安装IDE的Lombok插件
IDE配置步骤
IntelliJ IDEA配置
-
安装Lombok插件:
- 打开IDE设置(File > Settings)
- 转到插件市场(Plugins)
- 搜索"Lombok"并安装
- 重启IDE
-
启用注解处理:
- 打开IDE设置(File > Settings)
- 转到构建、执行、部署 > 编译器 > 注解处理器(Build, Execution, Deployment > Compiler > Annotation Processors)
- 勾选"启用注解处理"(Enable annotation processing)
- 点击应用(Apply)和确定(OK)
-
启用Lombok插件:
- 打开IDE设置(File > Settings)
- 转到插件 > 已安装(Plugins > Installed)
- 找到Lombok插件,确保它已启用
Eclipse配置
-
安装Lombok插件:
- 下载Lombok安装程序(https://projectlombok.org/setup/eclipse)
- 运行安装程序,选择Eclipse安装目录
- 重启Eclipse
-
启用注解处理:
- 打开项目属性(右键点击项目 > Properties)
- 转到Java编译器 > 注解处理(Java Compiler > Annotation Processing)
- 勾选"启用项目特定设置"(Enable project specific settings)
- 勾选"启用注解处理"(Enable annotation processing)
- 点击应用(Apply)和确定(OK)
Lombok的主要注解
Lombok注解总览
注解 | 功能描述 |
---|---|
@Data | 生成所有字段的getter/setter、toString()、equals()和hashCode()方法,以及无参构造方法 |
@Getter | 生成所有字段的getter方法 |
@Setter | 生成所有字段的setter方法 |
@NoArgsConstructor | 生成无参构造方法 |
@AllArgsConstructor | 生成全参数构造方法 |
@Builder | 生成建造者模式 |
@Slf4j | 自动生成日志对象 |
@EqualsAndHashCode | 生成equals和hashCode方法 |
@ToString | 生成toString方法 |
@RequiredArgsConstructor | 生成包含所有标记为@NonNull或final字段的构造方法 |
@Value | 生成不可变类,所有字段都是private和final的 |
@SneakyThrows | 自动处理受检异常 |
@Accessors | 控制生成的访问器(getter/setter)的行为 |
@Builder.Default | 为@Builder生成的建造者设置默认值 |
@SuperBuilder | 处理继承关系中的建造者模式 |
@NonNull | 标记字段或参数不能为null |
@Cleanup | 自动关闭资源 |
@Generated | 标记生成的代码 |
@UtilityClass | 生成工具类 |
@Experimental | 标记实验性功能 |
@Lombok | 自定义注解 |
@FieldNameConstants | 生成字段名称常量 |
@With | 生成不可变对象的with方法 |
@Log | 生成日志对象(通用) |
@CommonsLog | 生成Apache Commons Logging日志对象 |
@Flogger | 生成Google Flogger日志对象 |
@JBossLog | 生成JBoss日志对象 |
@Log4j | 生成Log4j日志对象 |
@Log4j2 | 生成Log4j2日志对象 |
@Slf4j | 生成SLF4J日志对象 |
@XSlf4j | 生成SLF4J扩展日志对象 |
1. @Data
最常用的注解,自动生成以下内容:
- 所有字段的getter和setter方法
- toString()方法
- equals()和hashCode()方法
- 无参构造方法
@Data
public class User {
private Long id;
private String username;
private String password;
private String email;
}
2. @Getter和@Setter
分别生成getter和setter方法,可以指定访问级别:
@Getter(AccessLevel.PUBLIC)
@Setter(AccessLevel.PROTECTED)
public class User {
private Long id;
private String username;
}
3. @NoArgsConstructor和@AllArgsConstructor
生成无参构造方法和全参数构造方法:
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String username;
private String password;
}
4. @Builder
生成建造者模式,方便创建对象:
@Builder
public class User {
private Long id;
private String username;
private String password;
}
// 使用方式
User user = User.builder()
.id(1L)
.username("zhangsan")
.password("123456")
.build();
5. @Slf4j
自动生成日志对象,无需手动定义:
@Slf4j
public class UserService {
public void createUser(User user) {
log.info("Creating user: {}", user.getUsername());
// 业务逻辑
log.debug("User created successfully");
}
}
6. @EqualsAndHashCode
生成equals和hashCode方法,可以指定包含或排除的字段:
@EqualsAndHashCode(of = {"id", "username"})
public class User {
private Long id;
private String username;
private String password; // 不参与equals和hashCode计算
}
7. @ToString
生成toString方法,可以指定包含或排除的字段:
@ToString(exclude = {"password"})
public class User {
private Long id;
private String username;
private String password; // 不会出现在toString结果中
}
8. @RequiredArgsConstructor
生成包含所有标记为@NonNull或final字段的构造方法:
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
@NonNull
private String applicationName;
}
9. @Value
生成不可变类,所有字段都是private和final的:
@Value
public class UserDTO {
Long id;
String username;
String email;
}
10. @SneakyThrows
自动处理受检异常,无需显式声明throws:
public class FileUtils {
@SneakyThrows
public static String readFile(String path) {
return Files.readString(Paths.get(path));
}
}
11. @Accessors
控制生成的访问器(getter/setter)的行为:
@Data
@Accessors(chain = true) // 支持链式调用
public class User {
private Long id;
private String username;
private String password;
}
// 使用方式
User user = new User()
.setId(1L)
.setUsername("zhangsan")
.setPassword("123456");
12. @Builder.Default
为@Builder生成的建造者设置默认值:
@Builder
public class User {
private Long id;
private String username;
@Builder.Default
private Integer status = 1; // 默认值为1
}
13. @SuperBuilder
处理继承关系中的建造者模式:
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class BaseEntity {
private Long id;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class User extends BaseEntity {
private String username;
private String password;
private String email;
}
// 使用方式
User user = User.builder()
.id(1L)
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.username("zhangsan")
.password("123456")
.email("zhangsan@example.com")
.build();
14. @NonNull
标记字段或参数不能为null:
public class UserService {
public void createUser(@NonNull User user) {
// 方法实现
}
}
15. @Cleanup
自动关闭资源:
public class FileUtils {
public static void copyFile(String source, String target) {
@Cleanup InputStream in = new FileInputStream(source);
@Cleanup OutputStream out = new FileOutputStream(target);
byte[] buffer = new byte[1024];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
}
}
16. @With
生成不可变对象的with方法:
@With
@Value
public class User {
Long id;
String username;
String email;
}
// 使用方式
User user = new User(1L, "zhangsan", "zhangsan@example.com");
User updatedUser = user.withEmail("new@example.com"); // 创建新对象,只修改email字段
17. @FieldNameConstants
生成字段名称常量:
@FieldNameConstants
public class User {
private Long id;
private String username;
private String password;
}
// 使用方式
String idField = User.Fields.id; // "id"
String usernameField = User.Fields.username; // "username"
18. @UtilityClass
生成工具类:
@UtilityClass
public class StringUtils {
public String reverse(String str) {
return new StringBuilder(str).reverse().toString();
}
public boolean isEmpty(String str) {
return str == null || str.isEmpty();
}
}
Lombok的优缺点
优点
- 减少样板代码:自动生成getter、setter等方法,减少代码量
- 提高可读性:代码更加简洁,关注业务逻辑而非样板代码
- 减少错误:自动生成的方法不容易出错
- 易于维护:添加新字段时,相关方法会自动更新
- 支持链式调用:@Accessors(chain = true)支持链式调用
- 提高开发效率:减少重复编写样板代码的时间
缺点
- IDE支持问题:某些IDE可能需要安装插件才能正确识别Lombok生成的代码
- 学习成本:需要学习Lombok的注解和用法
- 编译时生成:代码在编译时生成,可能影响编译速度
- 调试困难:生成的代码不在源代码中,调试时可能不太直观
- 版本兼容性:不同版本的Lombok可能有兼容性问题
- 可能隐藏问题:自动生成的方法可能掩盖一些设计问题
最佳实践
1. 合理使用@Data
@Data虽然方便,但可能生成过多不需要的方法。建议根据实际需求使用更精确的注解:
// 不推荐
@Data
public class User {
private Long id;
private String username;
private String password;
}
// 推荐
@Getter
@Setter
@ToString(exclude = "password")
@EqualsAndHashCode(of = "id")
public class User {
private Long id;
private String username;
private String password;
}
2. 使用@Builder.Default设置默认值
@Builder
public class User {
private Long id;
private String username;
@Builder.Default
private Integer status = 1; // 默认值为1
}
3. 使用@Slf4j替代手动创建日志对象
// 不推荐
public class UserService {
private static final Logger log = LoggerFactory.getLogger(UserService.class);
// ...
}
// 推荐
@Slf4j
public class UserService {
// ...
}
4. 使用@RequiredArgsConstructor进行依赖注入
// 不推荐
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// ...
}
// 推荐
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
// ...
}
5. 使用@Accessors控制访问器行为
@Data
@Accessors(chain = true) // 支持链式调用
public class User {
private Long id;
private String username;
private String password;
}
// 使用方式
User user = new User()
.setId(1L)
.setUsername("zhangsan")
.setPassword("123456");
6. 在实体类中使用Lombok
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
private String email;
private String phone;
private Integer status;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}
7. 在DTO和VO中使用Lombok
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private Long id;
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在6-20位之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
常见问题与解决方案
1. IDE不识别Lombok生成的代码
问题:IDE无法识别Lombok生成的getter、setter等方法,导致编译错误。
解决方案:
- 安装Lombok插件
- 启用注解处理(Enable annotation processing)
- 重新构建项目
2. 编译错误
问题:使用Lombok后出现编译错误。
解决方案:
- 确保Lombok版本与Java版本兼容
- 检查是否有冲突的注解
- 清理并重新构建项目
- 确保Lombok依赖配置正确
3. 序列化问题
问题:使用Lombok生成的类在序列化时出现问题。
解决方案:
- 使用@Getter和@Setter替代@Data
- 手动实现序列化方法
- 使用@JsonIgnore注解排除不需要序列化的字段
4. 继承问题
问题:使用Lombok的类在继承时出现问题。
解决方案:
- 使用@SuperBuilder代替@Builder处理继承关系
- 在父类上使用@Getter和@Setter,在子类上使用@Data
- 手动实现需要的方法
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class BaseEntity {
private Long id;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
@Getter
@Setter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
public class User extends BaseEntity {
private String username;
private String password;
private String email;
}
5. 与JPA/Hibernate的集成问题
问题:使用Lombok的类在JPA/Hibernate中出现问题。
解决方案:
- 使用@Getter和@Setter替代@Data
- 确保生成的equals和hashCode方法只使用实体的ID
- 使用@ToString.Exclude排除懒加载的集合
@Getter
@Setter
@ToString(exclude = {"orders"})
@EqualsAndHashCode(of = "id")
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Order> orders;
}
兼容性与IDE支持
Java版本兼容性
Lombok与不同Java版本的兼容性情况如下:
Lombok版本 | 兼容的Java版本 |
---|---|
1.18.30 | Java 8-21 |
1.18.28 | Java 8-20 |
1.18.26 | Java 8-19 |
1.18.24 | Java 8-18 |
1.18.22 | Java 8-17 |
1.18.20 | Java 8-16 |
1.18.18 | Java 8-15 |
1.18.16 | Java 8-14 |
1.18.14 | Java 8-13 |
1.18.12 | Java 8-12 |
1.18.10 | Java 8-11 |
1.18.8 | Java 8-10 |
1.18.6 | Java 8-9 |
1.18.4 | Java 8 |
1.18.2 | Java 8 |
1.18.0 | Java 8 |
1.16.22 | Java 8 |
1.16.20 | Java 8 |
1.16.18 | Java 8 |
1.16.16 | Java 8 |
1.16.14 | Java 8 |
1.16.12 | Java 8 |
1.16.10 | Java 8 |
1.16.8 | Java 8 |
1.16.6 | Java 8 |
1.16.4 | Java 8 |
1.16.2 | Java 8 |
1.16.0 | Java 8 |
注意事项:
- 使用较新版本的Java时,建议使用较新版本的Lombok
- 某些Lombok功能在较新版本的Java中可能不可用或行为不同
- 在升级Java版本时,可能需要同时升级Lombok版本
IDE支持情况
IntelliJ IDEA
IntelliJ IDEA对Lombok的支持非常好,但需要正确配置:
-
插件安装:
- 打开IDE设置(File > Settings)
- 转到插件市场(Plugins)
- 搜索"Lombok"并安装
- 重启IDE
-
注解处理:
- 打开IDE设置(File > Settings)
- 转到构建、执行、部署 > 编译器 > 注解处理器(Build, Execution, Deployment > Compiler > Annotation Processors)
- 勾选"启用注解处理"(Enable annotation processing)
- 点击应用(Apply)和确定(OK)
-
常见问题:
- 如果IDE无法识别Lombok生成的代码,尝试重新构建项目(Build > Rebuild Project)
- 如果出现"Lombok annotation processing does not work"错误,检查注解处理器设置
- 如果出现"Lombok plugin is not installed"错误,安装Lombok插件
Eclipse
Eclipse对Lombok的支持需要额外安装插件:
-
插件安装:
- 下载Lombok安装程序(https://projectlombok.org/setup/eclipse)
- 运行安装程序,选择Eclipse安装目录
- 重启Eclipse
-
注解处理:
- 打开项目属性(右键点击项目 > Properties)
- 转到Java编译器 > 注解处理(Java Compiler > Annotation Processing)
- 勾选"启用项目特定设置"(Enable project specific settings)
- 勾选"启用注解处理"(Enable annotation processing)
- 点击应用(Apply)和确定(OK)
-
常见问题:
- 如果Eclipse无法识别Lombok生成的代码,尝试清理项目(Project > Clean…)
- 如果出现"Lombok annotation processing does not work"错误,检查注解处理器设置
- 如果出现"Lombok plugin is not installed"错误,安装Lombok插件
VS Code
VS Code对Lombok的支持需要安装扩展:
-
扩展安装:
- 打开扩展市场(Extensions)
- 搜索"Lombok Annotations Support for VS Code"并安装
- 重启VS Code
-
Java扩展:
- 确保安装了"Extension Pack for Java"
- 确保安装了"Language Support for Java by Red Hat"
-
常见问题:
- 如果VS Code无法识别Lombok生成的代码,尝试重新加载窗口(Command Palette > Developer: Reload Window)
- 如果出现"Lombok annotation processing does not work"错误,检查Java扩展设置
NetBeans
NetBeans对Lombok的支持需要额外配置:
-
插件安装:
- 打开插件管理器(Tools > Plugins)
- 搜索"Lombok"并安装
- 重启NetBeans
-
注解处理:
- 打开项目属性(右键点击项目 > Properties)
- 转到编译(Compile)
- 勾选"启用注解处理"(Enable annotation processing)
- 点击确定(OK)
-
常见问题:
- 如果NetBeans无法识别Lombok生成的代码,尝试清理并构建项目(Run > Clean and Build Project)
- 如果出现"Lombok annotation processing does not work"错误,检查注解处理器设置
构建工具兼容性
Maven
Maven对Lombok的支持非常好,但需要正确配置:
-
依赖配置:
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency>
-
注解处理器配置:
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.11.0</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <annotationProcessorPaths> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
-
常见问题:
- 如果Maven编译时出现Lombok相关错误,尝试清理项目(mvn clean)
- 如果出现"Lombok annotation processing does not work"错误,检查注解处理器配置
Gradle
Gradle对Lombok的支持也很好,但需要正确配置:
-
依赖配置:
compileOnly 'org.projectlombok:lombok:1.18.30' annotationProcessor 'org.projectlombok:lombok:1.18.30'
-
常见问题:
- 如果Gradle编译时出现Lombok相关错误,尝试清理项目(gradle clean)
- 如果出现"Lombok annotation processing does not work"错误,检查注解处理器配置
常见兼容性问题及解决方案
1. 编译时错误
问题:使用Lombok后出现编译错误,如"找不到符号"或"不兼容的类型"。
解决方案:
- 确保Lombok版本与Java版本兼容
- 确保IDE已安装Lombok插件并启用了注解处理
- 清理并重新构建项目
- 检查是否有冲突的注解
2. 运行时错误
问题:使用Lombok生成的类在运行时出现错误,如"ClassNotFoundException"或"NoSuchMethodError"。
解决方案:
- 确保Lombok依赖配置正确
- 确保编译时生成的代码与运行时环境兼容
- 检查是否有版本冲突
3. 序列化问题
问题:使用Lombok生成的类在序列化时出现问题,如"NotSerializableException"。
解决方案:
- 使用@Getter和@Setter替代@Data
- 手动实现序列化方法
- 使用@JsonIgnore注解排除不需要序列化的字段
4. 与框架集成问题
问题:使用Lombok的类在与Spring、Hibernate等框架集成时出现问题。
解决方案:
- 使用@Getter和@Setter替代@Data
- 确保生成的equals和hashCode方法只使用实体的ID
- 使用@ToString.Exclude排除懒加载的集合
- 检查框架版本与Lombok版本的兼容性
5. 与测试框架集成问题
问题:使用Lombok的类在与JUnit、Mockito等测试框架集成时出现问题。
解决方案:
- 确保测试框架版本与Lombok版本兼容
- 使用@Getter和@Setter替代@Data
- 手动实现需要的方法
版本升级注意事项
在升级Lombok版本时,需要注意以下几点:
- 检查Java版本兼容性:确保新版本的Lombok与当前使用的Java版本兼容
- 检查IDE插件兼容性:确保IDE的Lombok插件与新版本的Lombok兼容
- 检查依赖冲突:确保没有其他依赖与Lombok冲突
- 测试功能兼容性:测试所有使用Lombok的功能,确保升级后仍然正常工作
- 查看更新日志:查看Lombok的更新日志,了解新版本的变化和可能的不兼容变更
最佳实践
- 使用最新稳定版本:尽量使用Lombok的最新稳定版本,以获得最新的功能和bug修复
- 明确指定版本:在依赖配置中明确指定Lombok版本,避免使用通配符
- 定期更新:定期更新Lombok版本,以获得最新的功能和bug修复
- 测试兼容性:在更新Lombok版本后,全面测试项目的兼容性
- 文档化配置:将Lombok的配置和版本信息文档化,方便团队成员了解
实际应用场景
1. 实体类定义
在JPA或MyBatis-Plus等ORM框架中定义实体类:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@Column(nullable = false, unique = true)
private String email;
@Column
private String phone;
@Column(nullable = false)
private Integer status;
@Column(name = "create_time", nullable = false, updatable = false)
private LocalDateTime createTime;
@Column(name = "update_time", nullable = false)
private LocalDateTime updateTime;
}
2. DTO和VO定义
定义数据传输对象和视图对象:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private Long id;
@NotBlank(message = "用户名不能为空")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度必须在6-20位之间")
private String password;
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserVO {
private Long id;
private String username;
private String email;
private String phone;
private Integer status;
private LocalDateTime createTime;
// 不包含敏感信息如密码
}
3. 服务层实现
在服务层中使用Lombok简化代码:
@Slf4j
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
public UserVO createUser(UserDTO userDTO) {
log.info("Creating user: {}", userDTO.getUsername());
// 检查用户名是否已存在
if (userRepository.existsByUsername(userDTO.getUsername())) {
log.warn("Username already exists: {}", userDTO.getUsername());
throw new BusinessException("用户名已存在");
}
// 创建用户实体
User user = User.builder()
.username(userDTO.getUsername())
.password(passwordEncoder.encode(userDTO.getPassword()))
.email(userDTO.getEmail())
.phone(userDTO.getPhone())
.status(1)
.createTime(LocalDateTime.now())
.updateTime(LocalDateTime.now())
.build();
// 保存用户
user = userRepository.save(user);
log.info("User created successfully: {}", user.getId());
// 转换为VO并返回
return convertToVO(user);
}
private UserVO convertToVO(User user) {
return UserVO.builder()
.id(user.getId())
.username(user.getUsername())
.email(user.getEmail())
.phone(user.getPhone())
.status(user.getStatus())
.createTime(user.getCreateTime())
.build();
}
}
4. 控制器实现
在控制器中使用Lombok简化代码:
@Slf4j
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
private final UserService userService;
@PostMapping
public Result<UserVO> createUser(@RequestBody @Valid UserDTO userDTO) {
log.info("收到创建用户的请求: {}", userDTO.getUsername());
UserVO userVO = userService.createUser(userDTO);
return Result.success(userVO);
}
@GetMapping("/{id}")
public Result<UserVO> getUser(@PathVariable Long id) {
log.info("收到获取用户的请求: {}", id);
UserVO userVO = userService.getUser(id);
return Result.success(userVO);
}
@PutMapping("/{id}")
public Result<UserVO> updateUser(@PathVariable Long id, @RequestBody @Valid UserDTO userDTO) {
log.info("收到更新用户的请求: {}", id);
UserVO userVO = userService.updateUser(id, userDTO);
return Result.success(userVO);
}
@DeleteMapping("/{id}")
public Result<Void> deleteUser(@PathVariable Long id) {
log.info("收到删除用户的请求: {}", id);
userService.deleteUser(id);
return Result.success();
}
}
5. 异常处理
使用Lombok简化异常类的定义:
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class BusinessException extends RuntimeException {
private String code;
private String message;
public BusinessException(String message) {
this("BUSINESS_ERROR", message);
}
public BusinessException(String code, String message) {
super(message);
this.code = code;
this.message = message;
}
}
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusinessException(BusinessException e) {
log.error("业务异常: {}", e.getMessage());
return Result.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidationException(MethodArgumentNotValidException e) {
log.error("验证异常: {}", e.getMessage());
String message = e.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return Result.error("VALIDATION_ERROR", message);
}
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
log.error("系统异常", e);
return Result.error("SYSTEM_ERROR", "系统异常,请稍后重试");
}
}
总结
Lombok是一个强大的Java库,可以显著减少样板代码,提高开发效率。通过合理使用Lombok的各种注解,可以使代码更加简洁、易读,同时保持代码的质量和可维护性。
在使用Lombok时,应该根据实际需求选择合适的注解,避免过度使用@Data等通用注解,以保持代码的清晰和可控。同时,需要注意Lombok的兼容性和IDE支持问题,确保开发环境的正确配置。