lombok是一个开源的代码生成库,能以简单的注解形式来简化Java类中的大量样板代码,提高开发人员的开发效率。
例如开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护,当属性多时会出现大量的getter/setter方法,这些显得很冗长也没有太多技术含量。
lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法,使代码看起来更简洁。
lombok对应的maven坐标:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
1. lombok插件安装
要使用lombok需要在IDE中安装对应的lombok插件。开发工具为IntelliJ IDEA,安装插件过程如下:
- 打开IntelliJ IDEA后点击菜单栏中的File–>Settings进入到设置页面
- 点击设置页面中的Plugins进行插件的安装,在右侧选择Browse repositories…,然后在搜索页面输入lombok,可以查询到下方的Lombok Plugin,鼠标点击Lombok Plugin可在右侧看到Install按钮,点击该按钮便可安装
注意:一般安装IntelliJ IDEA后,lombok插件已经自动安装
2. lombok常用注解
注解 | 说明 |
---|---|
@Setter | 注解在类或属性,注解在类时为所有属性生成setter方法,注解在属性上时只为该属性生成setter方法 |
@Getter | 使用方法同@Setter,区别在于生成的是getter方法 |
@ToString | 注解在类,添加toString方法 |
@EqualsAndHashCode | 注解在类,生成hashCode和equals方法 |
@NoArgsConstructor | 注解在类,生成无参的构造方法 |
@RequiredArgsConstructor | 注解在类,为类中需要特殊处理的属性生成构造方法,比如final和被@NonNull注解的属性 |
@AllArgsConstructor | 注解在类,生成包含类中所有属性的构造方法 |
@Data | 注解在类,生成setter/getter、equals、canEqual、hashCode、toString方法,如为final属性,则不会为该属性生成setter方法 |
@Slf4j | 注解在类,生成log变量,用于记录日志 |
@Builder | 将类转变为建造者模式 |
3. lombok入门案例
【步骤一】:创建maven工程zbbmeta-lombok-demo
并配置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>
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.7.15</version>
</parent>
<groupId>com.zbbmeta</groupId>
<artifactId>zbbmeta-lombok-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
</dependencies>
</project>
- 创建user表
create table user
(
id bigint null comment '主键',
name varchar(20) null,
age int null,
s_name varchar(20) null
);
-- 插入数据
INSERT INTO backend_db.user (id, name, age, s_name) VALUES (1740047068249387009, 'zbbmeta', 18, 'test1');
INSERT INTO backend_db.user (id, name, age, s_name) VALUES (1740047068350050306, 'springboot不念博客', 20, 'test2');
INSERT INTO backend_db.user (id, name, age, s_name) VALUES (1740047068350050307, 'springboot不念博客2', 22, null);
【步骤二】:创建User类并加入lombok提供的注解
package com.zbbmeta.entity;
import java.io.Serializable;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @TableName user
*/
@Data
public class User implements Serializable {
private Long id;
private String name;
private Integer age;
//注意该特殊字段
private String sName;
private static final long serialVersionUID = 1L;
}
【步骤三】:创建UserController
package com.zbbmeta.controller;
import com.zbbmeta.entity.User;
import com.zbbmeta.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* @author springboot不念博客
* @description: TODO
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
//查询User表数据
@GetMapping
public List<User> getUsers(){
List<User> list = userService.getUsers();
return list;
}
}
【步骤四】:使用POST发送请求 GET http://localhost:8899/user
[
{
"id": 1740047068249387009,
"name": "zbbmeta",
"age": 18,
"sname": null
},
{
"id": 1740047068350050306,
"name": "springboot不念博客",
"age": 20,
"sname": null
},
{
"id": 1740047068350050307,
"name": "springboot不念博客2",
"age": 22,
"sname": null
}
]
4.lombok存在问题
发现uese类的sName属性没有进行赋值
原因
Lombok对于第一个字母小写,第二个字母大写的属性生成的get-set方法和Mybatis以及想法还是说是Java官方认可的get-set方法生成的不一样
lombok生成的User对象
public class User
implements Serializable
{
private Long id;
private String name;
private Integer age;
private String sName;
private static final long serialVersionUID = 1L;
public void setId(Long id) {
this.id = id; }
public void setName(String name) { this.name = name; }
public void setAge(Integer age) { this.age = age; }
public void setSName(String sName) { this.sName = sName; }
public Long getId() {
return this.id;
} public String getName() {
return this.name;
} public Integer getAge() {
return this.age;
} public String getSName() {
return this.sName;
}
发现sName的set-get方法如下setSName和getSName不是我们想的setsName和getsName
Mybatis(3.4.6版本)解析get-set方法获取属性名字的源码:
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.reflection.property;
import java.util.Locale;
import org.apache.ibatis.reflection.ReflectionException;
/**
* @author Clinton Begin
*/
public final class PropertyNamer {
private PropertyNamer() {
// Prevent Instantiation of Static Class
}
public static String methodToProperty(String name) {
//is开头的一般是bool类型,直接从第二个(索引)开始截取(简单粗暴)
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {//set-get的就从第三个(索引)开始截取
name = name.substring(3);
} else {
throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
//下面这个判断很重要,解释如下
//第一句话:name.length()==1
// 对于属性只有一个字母的,例如private int x;
// 对应的get-set方法是getX();setX(int x);
//第二句话:name.length() > 1 && !Character.isUpperCase(name.charAt(1)))
//属性名字长度大于1,并且第二个(代码中的charAt(1),这个1是数组下标)字母是小写的
// 如果第二个char是大写的,那就直接返回name
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
//让属性名第一个字母小写,然后加上后面的内容
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
public static boolean isProperty(String name) {
return isGetter(name) || isSetter(name);
}
public static boolean isGetter(String name) {
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
}
public static boolean isSetter(String name) {
return name.startsWith("set") && name.length() > 3;
}
}
运行分析:
Mybatis解析get-set方法为属性名字测试
@GetMapping("/test")
public void getTest(){
String isName = "isName";
String getName = "getName";
String getnMetaType = "getsName";
String getNMetaType = "getSName";
Stream.of(isName,getName,getnMetaType,getNMetaType)
.forEach(methodName->System.out.println("方法名字是:"+methodName+" 属性名字:"+ PropertyNamer.methodToProperty(methodName)));
}
输出结果
方法名字是:isName 属性名字:name
方法名字是:getName 属性名字:name
方法名字是:getsName 属性名字:sName
方法名字是:getSName 属性名字:SName
- 1.修改属性名字,让第二个字母小写
- 2.如果数据库已经设计好,并且前后端接口对接好了,不想修改,手动添加 get 前缀,这样 Lombok 就会生成符合规范的方法名。
© 版权声明
本站文章由不念博客原创,未经允许严禁转载!
THE END