SpringBoot 內置工具類, 這也太好用了!
兄弟們,今天咱們要聊一個能讓你代碼量直接砍半的神器 ——SpringBoot 內置工具類!
你有沒有過這樣的經歷?寫代碼時突然遇到一個常見需求,比如處理字符串、操作集合、性能監控,然后本能地打開搜索引擎,開始瘋狂復制粘貼自己寫過的工具類?結果發現要么代碼冗余,要么有 bug,最后還得花時間調試。
但自從用了 SpringBoot,我發現這些需求早就被安排得明明白白!SpringBoot 就像一個瑞士軍刀,內置了各種開箱即用的工具類,從字符串處理到資源加載,從類型轉換到性能監控,幾乎涵蓋了日常開發的方方面面。
更絕的是,這些工具類不僅功能強大,還特別人性化。比如 StringUtils 類,判斷字符串是否為空的方法比女朋友的心思還細膩;CollectionUtils 類,處理集合就像在玩俄羅斯方塊,各種操作行云流水;StopWatch 類,性能監控比游戲里的計時器還直觀。
接下來,咱們就來逐一揭開這些工具類的神秘面紗,看看它們是如何讓你的代碼變得更優雅、更高效的。
一、字符串處理:StringUtils 的魔法
在 Java 開發中,字符串處理是最常見的操作之一。比如用戶輸入的用戶名是否為空,郵箱格式是否正確,日志信息的拼接等等。以前處理這些問題,我們可能需要自己寫一堆 if-else 判斷,或者依賴 Apache Commons Lang 等第三方庫。但現在,SpringBoot 內置的 StringUtils 類就能輕松搞定。
1.1 字符串判空:比女朋友的心思還細膩
字符串判空是最常見的操作之一,但不同的場景可能需要不同的判斷方式。比如,有的需求只需要判斷字符串是否為 null,有的則需要判斷是否為空字符串,還有的需要排除空格后的判斷。
StringUtils 類提供了多個方法來滿足這些需求:
- isEmpty(String str):判斷字符串是否為 null 或空字符串("")。
- isNotEmpty(String str):與isEmpty相反,判斷字符串不為 null 且不為空。
- hasLength(String str):判斷字符串是否有長度(即不為 null 且長度大于 0)。
- hasText(String str):判斷字符串是否有實際內容,即不為 null,長度大于 0,且至少包含一個非空格字符。
舉個栗子:
String username = " 張三 ";
boolean isEmpty = StringUtils.isEmpty(username); // false,因為字符串不為null且長度大于0
boolean isNotEmpty = StringUtils.isNotEmpty(username); // true
boolean hasLength = StringUtils.hasLength(username); // true
boolean hasText = StringUtils.hasText(username); // true,因為包含非空格字符如果我們想判斷用戶輸入的用戶名是否有效(非空且不含空格),可以這樣寫:
if (StringUtils.hasText(username.trim())) {
// 處理有效用戶名
} else {
// 提示用戶輸入有效用戶名
}1.2 字符串操作:懶人福音
除了判空,StringUtils 還提供了豐富的字符串操作方法,比如拼接、分割、替換等。
- join(Collection<?> coll, String separator):將集合中的元素用指定分隔符拼接成字符串。
- split(String str, String delimiter):按指定分隔符分割字符串,返回數組。
- replace(String inString, String oldPattern, String newPattern):替換字符串中的指定內容。
- deleteWhitespace(String str):刪除字符串中的所有空格。
比如,我們有一個用戶列表,需要將他們的名字用逗號拼接成一個字符串:
List<String> names = Arrays.asList("張三", "李四", "王五");
String result = StringUtils.join(names, ","); // 結果:"張三,李四,王五"再比如,我們想刪除字符串中的所有空格:
String str = " Hello World! ";
String trimmedStr = StringUtils.deleteWhitespace(str); // 結果:"HelloWorld!"1.3 其他實用方法:驚喜不斷
StringUtils 還有一些不太為人知但非常實用的方法,比如:
- endsWithIgnoreCase(String str, String suffix):忽略大小寫判斷字符串是否以指定后綴結尾。
- startsWithIgnoreCase(String str, String prefix):忽略大小寫判斷字符串是否以指定前綴開始。
- abbreviate(String str, int maxLength):截斷字符串到指定長度,超出部分用省略號表示。
舉個栗子:
String url = "https://www.baidu.com";
boolean endsWithCom = StringUtils.endsWithIgnoreCase(url, ".com"); // true
boolean startsWithHttps = StringUtils.startsWithIgnoreCase(url, "https"); // true
String longText = "這是一個很長很長很長的字符串,需要截斷到10個字符";
String abbreviatedText = StringUtils.abbreviate(longText, 10); // 結果:"這是一個..."二、集合操作:CollectionUtils 的十八般武藝
集合操作也是日常開發中的高頻需求,比如判斷集合是否為空、合并集合、查找元素等。SpringBoot 的 CollectionUtils 類提供了一系列便捷的方法,讓集合操作變得輕松愉快。
2.1 集合判空:簡單粗暴
CollectionUtils 提供了兩個方法來判斷集合是否為空:
- isEmpty(Collection<?> collection):判斷集合是否為 null 或沒有元素。
- isNotEmpty(Collection<?> collection):與isEmpty相反,判斷集合不為 null 且至少有一個元素。
比如:
List<String> list = new ArrayList<>();
boolean isEmpty = CollectionUtils.isEmpty(list); // true
boolean isNotEmpty = CollectionUtils.isNotEmpty(list); // false對于 Map 類型,CollectionUtils 也提供了類似的方法:
- isEmpty(Map<?,?> map):判斷 Map 是否為 null 或沒有鍵值對。
- isNotEmpty(Map<?,?> map):與isEmpty相反。
2.2 集合操作:玩出花樣
除了判空,CollectionUtils 還提供了很多實用的操作方法:
- mergeArrayIntoCollection(Object array, Collection<E> collection):將數組中的元素添加到集合中。
- findFirstMatch(Collection<?> source, Collection<?> candidates):在 source 集合中查找第一個出現在 candidates 集合中的元素。
- findValueOfType(Collection<?> collection, Class<T> type):在集合中查找指定類型的元素。
舉個栗子:
String[] array = {"a", "b", "c"};
List<String> list = new ArrayList<>();
CollectionUtils.mergeArrayIntoCollection(array, list); // list變為["a", "b", "c"]
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> candidates = Arrays.asList(3, 6, 9);
Integer firstMatch = CollectionUtils.findFirstMatch(numbers, candidates); // 結果:3
List<Object> objects = Arrays.asList(1, "hello", 3.14);
Integer integerValue = CollectionUtils.findValueOfType(objects, Integer.class); // 結果:1
String stringValue = CollectionUtils.findValueOfType(objects, String.class); // 結果:"hello"2.3 注意事項:避坑指南
雖然 CollectionUtils 很強大,但也有一些需要注意的地方。比如,hasUniqueObject(Collection<?> collection)方法用于判斷集合中的元素是否唯一,但該方法存在 bug!它使用==運算符來比較元素,而不是equals方法。如果集合中的元素是對象,且沒有重寫equals和hashCode方法,可能會得到錯誤的結果。
因此,在實際開發中,不建議使用hasUniqueObject方法,而是應該自己實現邏輯來判斷集合元素的唯一性。
三、性能監控:StopWatch 的精準計時
在開發過程中,我們經常需要了解某個代碼塊的執行時間,以便進行性能優化。SpringBoot 的 StopWatch 類就是一個簡單而強大的性能監控工具。
3.1 基本用法:簡單幾步
使用 StopWatch 非常簡單,只需以下幾步:
- 創建 StopWatch 實例。
- 調用start()方法開始計時。
- 執行需要計時的代碼塊。
- 調用stop()方法停止計時。
- 調用getTotalTimeMillis()方法獲取總執行時間(毫秒),或prettyPrint()方法輸出格式化的結果。
舉個栗子:
StopWatch stopWatch = new StopWatch();
stopWatch.start("任務1");
// 執行耗時操作
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
stopWatch.stop();
stopWatch.start("任務2");
// 執行另一個耗時操作
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());輸出結果:
StopWatch '': running time (millis) = 1504
-----------------------------------------
ms % Task name
-----------------------------------------
1001 66% 任務1
503 33% 任務23.2 高級用法:靈活控制
StopWatch 還支持更靈活的使用方式,比如:
- start(String taskName):為指定的任務名稱開始計時。
- getTotalTimeMillis():獲取所有任務的總執行時間。
- getTaskCount():獲取已完成的任務數量。
- getLastTaskInfo():獲取最后一個任務的信息。
例如,我們可以在一個方法中記錄多個任務的執行時間:
public void process() {
StopWatch stopWatch = new StopWatch("數據處理");
stopWatch.start("數據讀取");
// 讀取數據
stopWatch.stop();
stopWatch.start("數據轉換");
// 轉換數據
stopWatch.stop();
stopWatch.start("數據寫入");
// 寫入數據
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
}3.3 注意事項:適用場景
StopWatch 是一個輕量級的計時工具,適合單進程內的性能監控。如果需要更復雜的性能分析,比如分布式系統的性能追蹤,建議使用專業的性能分析工具,如 JProfiler、VisualVM 等。
四、類型轉換:ConversionService 的智能轉換
在 Web 開發中,經常需要將請求參數轉換為 Java 對象,或者在不同數據類型之間進行轉換。SpringBoot 的 ConversionService 提供了強大的類型轉換功能,支持自動轉換常見的數據類型,如字符串轉整數、日期等。
4.1 默認轉換器:開箱即用
SpringBoot 默認注冊了一系列轉換器,使得控制器方法可以直接接收 Integer、Long、Date 等類型的參數,無需手動轉換。例如:
- StringToIntegerConverter:將字符串轉換為 Integer。
- StringToLocalDateConverter:將字符串轉換為 LocalDate(默認格式為 yyyy-MM-dd)。
- StringToBooleanConverter:將字符串(如 "true"/"false")轉換為 Boolean。
舉個栗子,在控制器中:
@GetMapping("/user")
public User getUser(@RequestParam("age") Integer age, @RequestParam("birthday") LocalDate birthday) {
// 使用age和birthday參數
}當請求參數為age=25&birthday=2023-10-01時,ConversionService 會自動將字符串 "25" 轉換為 Integer 類型,將字符串 "2023-10-01" 轉換為 LocalDate 類型。
4.2 自定義轉換器:按需擴展
如果默認轉換器無法滿足需求,我們可以自定義轉換器。例如,需要將字符串 "10s" 轉換為 Duration 類型:
- 實現Converter接口:
public class StringToDurationConverter implements Converter<String, Duration> {
@Override
public Duration convert(String source) {
return Duration.parse(source);
}
}- 將自定義轉換器注冊到 ConversionService 中:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new StringToDurationConverter());
}
}這樣,在控制器中就可以直接接收 Duration 類型的參數:
@GetMapping("/time")
public void processTime(@RequestParam("duration") Duration duration) {
// 使用duration參數
}4.3 注意事項:格式問題
如果日期格式不符合默認規則(如需要 dd/MM/yyyy 格式),可以通過@DateTimeFormat注解指定格式:
@GetMapping("/user")
public User getUser(@RequestParam("birthday") @DateTimeFormat(pattern = "dd/MM/yyyy") LocalDate birthday) {
// 使用birthday參數
}五、資源處理:ResourceUtils 和 FileCopyUtils 的高效操作
在開發中,經常需要讀取類路徑下的資源文件,或者進行文件復制、流處理等操作。SpringBoot 的 ResourceUtils 和 FileCopyUtils 類提供了便捷的方法來完成這些任務。
5.1 ResourceUtils:輕松獲取資源
ResourceUtils 可以方便地獲取類路徑、文件系統中的資源。例如:
- getResource(String location):獲取指定位置的資源。
- getFile(String location):獲取資源對應的文件。
舉個栗子:
// 獲取類路徑下的config.properties文件
File configFile = ResourceUtils.getFile("classpath:config.properties");
// 獲取文件系統中的文件
File localFile = ResourceUtils.getFile("file:/path/to/local/file.txt");5.2 FileCopyUtils:高效文件操作
FileCopyUtils 提供了一系列方法來處理文件和流,比如:
- copyToByteArray(File in):將文件內容讀取到字節數組中。
- copy(InputStream in, OutputStream out):將輸入流的內容復制到輸出流中。
- copyToString(Reader in):將輸入流的內容讀取為字符串。
例如,讀取類路徑下的文本文件:
String content = FileCopyUtils.copyToString(
new InputStreamReader(ResourceUtils.getFile("classpath:data.txt").toURI().toURL().openStream(), StandardCharsets.UTF_8)
);再比如,復制文件:
File sourceFile = new File("source.txt");
File targetFile = new File("target.txt");
FileCopyUtils.copy(sourceFile, targetFile);5.3 注意事項:資源釋放
在使用流操作時,一定要注意關閉流,避免資源泄漏。可以使用 Java 7 的 try-with-resources 語句來自動關閉流:
try (InputStream inputStream = ResourceUtils.getFile("classpath:data.txt").toURI().toURL().openStream();
OutputStream outputStream = new FileOutputStream("output.txt")) {
FileCopyUtils.copy(inputStream, outputStream);
} catch (IOException e) {
e.printStackTrace();
}六、其他實用工具類
除了上述工具類,SpringBoot 還提供了許多其他實用的工具類,比如:
6.1 BeanUtils:對象操作神器
BeanUtils 可以方便地復制 Bean 屬性、實例化對象等。例如:
- copyProperties(Object source, Object target):將源對象的屬性復制到目標對象。
- instantiateClass(Class<?> clazz):實例化指定類的對象。
舉個栗子:
User sourceUser = new User("張三", 25);
User targetUser = new User();
BeanUtils.copyProperties(sourceUser, targetUser); // targetUser的name和age被賦值為"張三"和25
Class<User> userClass = User.class;
User user = BeanUtils.instantiateClass(userClass); // 創建User對象6.2 Assert:斷言工具
Assert 類用于數據合法性檢查,拋出有意義的異常信息。例如:
- notNull(Object object, String message):檢查對象是否為 null。
- hasText(String text, String message):檢查字符串是否有實際內容。
舉個栗子:
public void updateUser(User user) {
Assert.notNull(user, "用戶對象不能為空");
Assert.hasText(user.getName(), "用戶姓名不能為空");
Assert.isTrue(user.getAge() > 0, "用戶年齡必須大于0");
// 更新用戶邏輯
}6.3 StreamUtils:流處理專家
StreamUtils 提供了一系列處理流的方法,比如:
- copyToByteArray(InputStream in):將輸入流的內容讀取到字節數組中。
- copyToString(InputStream in, Charset charset):將輸入流的內容讀取為字符串。
- copy(InputStream in, OutputStream out):將輸入流的內容復制到輸出流中。
例如,讀取請求體中的 JSON 數據:
@PostMapping("/user")
public void createUser(HttpServletRequest request) throws IOException {
String json = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
// 解析json數據
}七、總結:工具類的正確打開方式
通過本文的介紹,相信你已經對 SpringBoot 內置工具類有了更深入的了解。這些工具類不僅能提高開發效率,還能讓代碼更加優雅、健壯。
在實際開發中,我們應該:
- 優先使用 SpringBoot 內置工具類,避免重復造輪子。
- 熟悉常用工具類的方法和適用場景,減少不必要的代碼。
- 注意工具類的注意事項,避免常見錯誤。
- 結合項目需求,合理擴展和自定義工具類。
































