背景
業務系統開發時,你是否踩過這樣的坑:
- 業務說串列篩選姓名精準查詢查不到人?
- 匯入資料時,明明看起來一樣的ID卻匹配不到DB里的資料?
- 看起來一樣的內容,SQL Group By 時出現好幾行?
- ……
DEBUG后發現,原來要么時用戶傳入或者匯入的資料里有個空格,要么是資料庫里不知道什么時候已經存了一個前后有空格的值,
總之,我們不知道它什么時候暴雷,開放的介面你也無法確定呼叫方(前端、服務間RPC呼叫、本應用內呼叫等)是否都幫你去除了兩端空格,為了保證代碼的健壯性,你只好寫了如下般的代碼:
@PostMapping(value = "https://www.cnblogs.com/login")
public ResponseEntity<UserDetails> login(String username, String password, String captcha) {
Assert.hasText(username, "用戶名不能為空");
Assert.hasText(password, "密碼不能為空");
Assert.hasText(captcha, "驗證碼不能為空");
// 判斷具有有效值后,還需要去除兩端空白符
username = username.trim();
password = password.trim();
captcha = captcha.trim();
// Security Authorization...
return new ResponseEntity(null, HttpStatus.OK);
}
又或者,物件物體里更惡心的:
@Data
static class Student {
private String name;
private String phone;
private String idCard;
private String city;
private String specializedSubject;
}
@PostMapping(value = "https://www.cnblogs.com/save")
public ResponseEntity<UserDetails> save(Student student) {
Assert.notNull(student, "引數不能為空");
Assert.hasText(student.getName(), "學生姓名不能為空");
Assert.hasText(student.getIdCard(), "學生身份證號不能為空");
// 判斷具有有效值后,還需要去除兩端空白符
student.setName(student.getName().trim());
student.setIdCard(student.getIdCard().trim());
// 可選值如果有長度,還需要去除兩端空白符;似乎感覺絕大多數的String型別引數都要去除兩端空白符
if (StringUtils.hasLength(student.getCity())) {
student.setCity(student.getCity().trim());
}
if (StringUtils.hasLength(student.getPhone())) {
student.setPhone(student.getPhone().trim());
}
if (StringUtils.hasLength(student.getSpecializedSubject())) {
student.setSpecializedSubject(student.getSpecializedSubject().trim());
}
// Service call...
return new ResponseEntity(null, HttpStatus.OK);
}
然后你發現,似乎整個業務系統里,絕大多數的字串型別引數,都應該去除兩端空白符,可是每個欄位你都這么寫一遍,不僅篇幅過長,還極其惡心人,
那怎么辦?又想代碼健壯一點,避免暴雷,又想代碼簡潔增強可讀性,
那你可以試一下AutoTrim這個小巧的工具,它可以幫你優雅地解決這個情況,
AutoTrim
概述
**AutoTrim**是一個小巧且nice的APT工具,它能夠幫你減少String型別引數的trim()代碼書寫,
什么APT工具?就是類似于Lombok,APT(Annotation Processing Tool),也就是大家常說的編譯期間注解處理器,
注解
@AutoTrim對注釋的物件進行AutoTrim操作,即添加 string == null ? null : string.trim() 代碼.@AutoTrim.Ignored進行AutoTrim操作時,忽略對該注釋的物件,
快速使用
- 添加依賴
<dependency>
<groupId>com.supalle</groupId>
<artifactId>auto-trim</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
- 使用注解改寫上面的偽代碼
- 偽代碼 1 改寫:
// 只需要在方法上用@AutoTrim注解修飾即可
@AutoTrim
@PostMapping(value = "https://www.cnblogs.com/login")
public ResponseEntity<UserDetails> login(String username, String password, String captcha) {
Assert.hasText(username, "用戶名不能為空");
Assert.hasText(password, "密碼不能為空");
Assert.hasText(captcha, "驗證碼不能為空");
// Security Authorization
return new ResponseEntity(null, HttpStatus.OK);
}
// 編譯后,用IDEA查看反編譯結果
@PostMapping(value = "https://www.cnblogs.com/login")
public ResponseEntity<UserDetails> login(String username, String password, String captcha) {
username = username == null ? null : username.trim(); // 已自動添加
password = password == null ? null : password.trim(); // 已自動添加
captcha = captcha == null ? null : captcha.trim(); // 已自動添加
Assert.hasText(username, "用戶名不能為空");
Assert.hasText(password, "密碼不能為空");
Assert.hasText(captcha, "驗證碼不能為空");
// Security Authorization...
return new ResponseEntity(null, HttpStatus.OK);
}
- 偽代碼 2 改寫:
// 直接給物體加上@AutoTrim注解
@Data
@AutoTrim
static class Student {
private String name;
private String phone;
private String idCard;
private String city;
private String specializedSubject;
}
// 那么方法里的代碼就可以簡化為:
@PostMapping(value = "https://www.cnblogs.com/save")
public ResponseEntity<UserDetails> save(Student student) {
Assert.notNull(student, "引數不能為空");
Assert.hasText(student.getName(), "學生姓名不能為空");
Assert.hasText(student.getIdCard(), "學生身份證號不能為空");
// Service call...
return new ResponseEntity(null, HttpStatus.OK);
}
// 編譯后,用IDEA查看反編譯結果
static class Student {
private String name;
private String phone;
private String idCard;
private String city;
private String specializedSubject;
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public void setPhone(String phone) {
this.phone = phone == null ? null : phone.trim();
}
public void setIdCard(String idCard) {
this.idCard = idCard == null ? null : idCard.trim();
}
public void setCity(String city) {
this.city = city == null ? null : city.trim();
}
public void setSpecializedSubject(String specializedSubject) {
this.specializedSubject = specializedSubject == null ? null : specializedSubject.trim();
}
}
代碼一下子就干凈起來了,
@AutoTrim.Ignored
如果你想忽略個別引數、欄位、方法被@AutoTrim影響呢,可以使用@AutoTrim.Ignored注解對目標進行標記,比如:
- 方法內多個
String型別的形參,忽略某一個不需要trim()操作:
@AutoTrim
@PostMapping(value = "https://www.cnblogs.com/login")
public ResponseEntity<UserDetails> login(String username, String password
, @AutoTrim.Ignored String captcha) {
Assert.hasText(username, "用戶名不能為空");
Assert.hasText(password, "密碼不能為空");
Assert.hasText(captcha, "驗證碼不能為空");
// Security Authorization
return new ResponseEntity(null, HttpStatus.OK);
}
// 編譯后,用IDEA查看反編譯結果
@PostMapping(value = "https://www.cnblogs.com/login")
public ResponseEntity<UserDetails> login(String username, String password
, String captcha) {
username = username == null ? null : username.trim(); // 已自動添加
password = password == null ? null : password.trim(); // 已自動添加
// 編譯時就不會為captcha引數添加 auto-trim 的代碼
Assert.hasText(username, "用戶名不能為空");
Assert.hasText(password, "密碼不能為空");
Assert.hasText(captcha, "驗證碼不能為空");
// Security Authorization...
return new ResponseEntity(null, HttpStatus.OK);
}
- JavaBean里,某個
String型別的屬性不需要trim()操作:
@Data
@AutoTrim
static class Student {
private String name;
@AutoTrim.Ignored
private String phone;
private String idCard;
private String city;
private String specializedSubject;
}
// 編譯后,用IDEA查看反編譯結果
static class Student {
private String name;
private String phone;
private String idCard;
private String city;
private String specializedSubject;
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public void setPhone(String phone) {
this.phone = phone;// 編譯時就不會為phone屬性的Setter方法添加 auto-trim 的代碼
}
public void setIdCard(String idCard) {
this.idCard = idCard == null ? null : idCard.trim();
}
public void setCity(String city) {
this.city = city == null ? null : city.trim();
}
public void setSpecializedSubject(String specializedSubject) {
this.specializedSubject = specializedSubject == null ? null : specializedSubject.trim();
}
}
怎么樣,是不是非常簡單咧,
特性
- 小巧,單一目標功能,簡單易用;
- 支持_JDK8~JDK21_;
- 支持class類、介面、子類、匿名內部類的類級別;
- 支持屬性上使用;
- 支持方法上使用;
- 支持方法形參上使用;
- 支持
final修飾的形參;
原始碼倉庫
開源協議:Apache License 2.0
GitHub:https://github.com/supalle/auto-trim
Gitee:https://gitee.com/Supalle/auto-trim
如果使用中有什么問題歡迎各位小伙伴提issues反饋,我會長期維護這個親兒子專案,
更新周期
AutoTrim定位為單一功能,輕包袱的工具,因此暫時不會加太多其他與之無關的功能,如有新的APT點子,會另開專案推出,因此更新的頻率不會太頻繁,
- 修復已知bug后,發布小版本;
- JDK發布新版本后,會第一時間支持新的JDK版本,然后發布大版本,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546952.html
標籤:Java
