Spring Easy

Spring Easy

用途

通過自動配置,實現了一些國內 Spring Boot 開發時需要在 Spring Boot 框架基礎上完成的一些配置工作,可以提升基于 Spring Boot 開發 Web 應用的效率。

安裝

使用 Maven 進行包管理,可以從中央倉庫安裝依賴:

<dependency><groupId>cn.icexmoon</groupId><artifactId>spring-easy-boot-starter</artifactId><version>1.0.0</version>
</dependency>

功能說明

封裝控制器方法返回值

提供對 JSON 返回的統一封裝。

比如 Controller 方法:

@GetMapping("/say")
public Map<String, String> say() {return Map.of("msg", "hello");
}

Spring Boot 默認返回:

{"msg": "hello"
}

使用本應用后:

{"success": true,"message": null,"data": {"msg": "hello"}
}

這里利用返回值處理器 ResponseBodyAdvice 對控制器方法的返回值進行統一封裝,將其封裝為 Result 對象的 data 屬性,然后由 Spring 的 ResponseBody 返回值處理器(Return Value Resolver)進行處理,即使用消息轉換器(默認為 Jackson)將 Result 對象解析成 JSON 字符串作為響應報文體返回。

需要注意的是,由 @Response 注解標記,且返回類型是 String 的控制器方法比較特殊:

@GetMapping("/msg")
public String msg() {return "<h1>hello</h1>";
}

這個控制器方法的返回值不走 ResponseBody 返回值處理器,會被另一個返回值處理器處理,處理方式也很簡單,直接作為字符串填充到響應報文體中返回。這也符合開發者需要,因為這種方式定義的控制器方法,通常會直接返回 Html 片段等,不需要返回值處理器進行消息轉換等額外處理。

因此,對于這種類型的控制器方法,本項目同樣不會進行封裝,以便行為和 Spring Boot 的默認實現保持一致。

如果你需要返回給前端的內容只有一個字符串,且希望返回標準封裝的形式,可以直接構造 Result 對象并返回:

@GetMapping("/msg2")
public Result<String> msg2() {return Result.success("hello", null);
}

本項目不會對 Result 類型的返回進行再次包裝。

對于其他形式的基本類型返回,本項目都會進行封裝,比如:

@GetMapping("/void")
public void voidMethod() {
}@GetMapping("/boolean")
public boolean booleanMethod() {return false;
}@GetMapping("/int")
public int intMethod() {return 11;
}

都會包裝并返回 Result 對象的 JSON 字符串。

統一處理并返回錯誤信息

項目使用異常處理器(Exception Handler)ErrorControllerAdvice 對異常進行統一處理,并封裝成標準返回值返回。

比如會產生異常的控制器方法:

@GetMapping("/default")
public Result<Void> defaultError() {int i = 1 / 0;return Result.success();
}

返回報文:

{"success": false,"message": "/ by zero","data": null
}

控制臺中會由cn.icexmoon.springeasy.boot.ErrorControllerAdvice輸出相關異常信息日志,日志級別為error

業務層面產生的異常,比如缺少用戶信息等,應當使用自定義異常 BusinessException,這個異常同樣會被捕獲并封裝成統一格式返回,區別在于默認異常的 HTTP 狀態碼是 500,業務異常的 HTTP 狀態碼是 200。

可以在任意需要返回業務錯誤的地方直接拋出 BusinessException,或者在需要的時候將其它類型的異常包裝成業務異常拋出:

@GetMapping("/business")
public Result<Void> businessError() {try {int i = 1 / 0;} catch (Throwable e) {Map<String, ?> exceptionData = Map.of("cause", e,"businessCode", "1001");throw BusinessException.builder().cause(e).message(e.getMessage()).data(exceptionData).build();}return Result.success();
}

BusinessException 的 data 屬性可以存放需要傳遞給前端的額外信息,它將被保存到 Result 對象的 data 屬性后返回給前端。

對于 Servlet 異常(比如 Filter 產生的),定義了一個控制器 ServletErrorController 進行處理,以同樣的返回標準 Result。控制器方法中只會進行簡單異常信息打印和控制臺異常調用日志輸出:

@ResponseBody
public Result<?> error(HttpServletRequest request) {Throwable error = (Throwable) request.getAttribute((RequestDispatcher.ERROR_EXCEPTION));log.error(error.getMessage(), error);return Result.fail("Servlet 錯誤:" + error.getMessage());
}

如果不滿足需要,可以覆蓋這個 Bean 進行自定義。

該控制器默認使用 /error 路徑進行內部跳轉,如果你不想使用該路徑(通常是被其它控制器方法已經占用),可以通過配置文件中的屬性進行修改:

spring-easy:boot-starter:error-page-path: /servlet_error

時間類型轉換

項目添加了針對 LocalDateTimeLocalDate 的類型轉換器,以支持國內常見的 yyyy-MM-dd HH:mm:ssyyyy-MM-dd 格式的日期/時間字符串轉換。

啟用本項目后可以直接通過 URL 的查詢參數傳遞時間字符串:

localhost:8080/hello/time?time=2025-07-09 11:08:03

控制器方法:

@GetMapping("/time")
public LocalDateTime time(@RequestParam LocalDateTime time) {log.info(time.toString());return time;
}

LocalDateTime類型的@RequestParam參數可以被正常解析,不需要使用其他額外的類型轉換注解。

為了能夠讓 jackson 正確解析和編碼同樣格式的時間字符串,本項目添加了相應的 jackson 解析器/編碼器。因此如果使用本項目的時間類型轉換功能,最好不要替換 Spring Boot 默認的消息轉換器 jackson。

IEnum 枚舉類型轉換

如果你的項目使用 MyBatisPlus,且實體類中存在枚舉字段,使用IEnum接口是最方便的:

@TableName(value = "user")
@Data
public class User {public enum Sex implements IDescEnum<Integer> {MALE(5, "男"), FEMALE(6, "女");private final Integer value;private final String desc;Sex(Integer value, String desc) {this.value = value;this.desc = desc;}@Overridepublic Integer getValue() {return value;}@Overridepublic String getDesc() {return desc;}}/****/@TableId(type = IdType.AUTO)private Long id;/*** 姓名*/private String name;/*** 性別 5 男,6 女*/private Sex sex;
}

這里使用的 IDescEnum 接口是對 IEnum 接口的一個擴展,本質是一樣的,只是額外記錄枚舉常量的中文信息。

MyBatisPlus 實現了 Service 層和數據庫的 IEnum 和 int 值的轉換,但如果將 IEnum 類型的枚舉用于控制器方法參數或返回值,就會被 Spring Boot 當做普通的枚舉類型進行處理。

本項目通過添加類型轉換器和 jackson 編碼器/解析器,實現了 int 和 IEnum 枚舉的轉換。

關閉部分功能

本項目默認開啟所有功能,如果要關閉相關功能,可以通過配置文件:

spring-easy:boot-starter:wrap-result: truewrap-error: truetime-converter: trueenum-converter: true

相應的屬性設置為 false 即可。需要更高程度的自由定制可以查看源碼后覆蓋相應的 bean 定義。

示例

spring-easy-test 是一個包含了所有功能的完整 Spring Boot 示例,展示了如何添加本項目以及使用相應功能。

開源

項目使用 Apache 2 許可證開源,倉庫地址 icexmoon/spring-easy。

項目代碼結構為:

  • spring-easy-boot-starter,Spring Boot 的自動配置相關
  • spring-easy-parent,Maven 依賴版本控制以及項目編譯
  • spring-easy-test,一個用于測試/示例的 Spring Boot Web 項目
  • spring-easy-util,核心類,包含 jackson 解析器/編碼器、Spring 類型轉換器等

反饋

Issues · icexmoon/spring-easy

更新日志

1.0.0

發布

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88758.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88758.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88758.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Node.js】文本與 pdf 的相互轉換

pdf 轉文本 主要使用 pdf-parse 這個庫&#xff0c;直接識別提取我們 pdf 文件中的文字。 const express require("express"); const fs require("fs"); const PDFParser require("pdf-parse"); const cors require("cors");const…

分布式ID方案

目錄 &#x1f4ca; 分布式ID方案核心指標對比 &#x1f50d; 分方案深度解析 ?? 1. UUID (Universally Unique Identifier) ?? 2. Snowflake (Twitter開源) ?? 3. 美團Leaf 號段模式 Snowflake模式 &#x1f504; 4. 百度UidGenerator &#x1f680; 5. CosId …

張量類型轉換

一.前言本章節我們來講解張量的類型轉換&#xff0c;掌握張量的轉換方法&#xff0c;張量的類型轉換也是經常使?的?種操作&#xff0c;是必須掌握的知識點。在本?節&#xff0c;我們主要學習如何將 numpy 數組和 PyTorch Tensor 的轉化?法.二.張量轉換為 numpy 數組使? Te…

JavaEE-初階-多線程初階

概念第一個多線程程序 可以通過查看jdk路徑來找到jdk的控制可以通過jconsole來查看線程。創建線程這是實現多線程的其中一種方法&#xff0c;繼承Thread類&#xff0c;實現run方法&#xff0c;之后實例化繼承了Thread類的MyThread方法&#xff0c;調用start方法&#xff0c;就會…

解釋全連接層的“參數數量”和“計算過程”,保證像看動畫片一樣直觀~

假設場景輸入圖像&#xff1a;一張極小的 灰度圖&#xff08;即 H2,W2&#xff0c;共4個像素&#xff09;&#xff0c;像素值如圖所示&#xff1a;隱藏層&#xff1a;假設隱藏層也是 &#xff08;即 H2,W2&#xff0c;共4個神經元&#xff09;&#xff0c;每個神經元用 ( 表示…

DOM編程實例(不重要,可忽略)

文章目錄 簡介 表格增加刪除&#xff0c;效果如下圖 樣式屬性案例 簡介 DOM---表格添加刪除&#xff0c;樣式屬性案例 表格增加刪除&#xff0c;效果如下圖 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><met…

?Windows API 介紹及核心函數分類表

Windows API 介紹? Windows API&#xff08;Application Programming Interface&#xff09;&#xff0c;也稱為WinAPI&#xff0c;是微軟Windows操作系統的核心編程接口。它提供了一系列函數、消息、數據結構、宏和系統服務&#xff0c;允許開發者創建運行在Windows平臺上的應…

Kubernetes Dashboard UI 部署安裝

K8S 集群環境&#xff1a; Ubuntu 24 / K8S 1.28.21. 推薦使用helm 安裝Kubernetes Dashboardsudo snap install helm --classic2. 部署Kubernetes Dashboard# Add kubernetes-dashboard repository helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboar…

python-enumrate函數

文章目錄基本語法基本用法基本遍歷指定起始索引實際應用場景需要索引的循環創建字典映射處理文件行號與range(len())對比注意事項enumerate()是Python內置函數&#xff0c;用于在遍歷序列&#xff08;如列表、元組或字符串&#xff09;時同時獲取索引和值。基本語法 enumerate…

FPGA通信設計十問

1. FFT有什么用&#xff1f;FFT&#xff08;快速傅里葉變換&#xff09;是離散傅里葉變換&#xff08;DFT&#xff09;的高效實現算法&#xff0c;它的核心作用是快速將信號從時域轉換到頻域&#xff0c;從而簡化信號分析和處理的過程。自然界的信號&#xff08;如聲音、圖像、…

代理模式——Java

代理模式 在Java中代理模式是一種設計模式&#xff0c;是通過代理類來代替原始的對象&#xff0c;可以在不改變原始對象的基礎上&#xff0c;對它進行擴展&#xff08;新增一些新功能&#xff09;。在目標方法的執行的執行前后添加一些自定義的方法。 靜態代理 步驟&#xff1a…

基于Catboost算法的茶葉數據分析及價格預測系統的設計與實現

文章目錄有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主項目介紹數據采集數據預處理數據分析與可視化大屏設計模型構建系統展示每文一語有需要本項目的代碼或文檔以及全部資源&#xff0c;或者部署調試可以私信博主 項目介紹 本研究基于京東官網…

【數據庫基礎 1】MySQL環境部署及基本操作

目錄 一、MySQL部署 1.更新軟件包列表 2.查看合適的安裝包&#xff1a; 3.安裝MySQL 4.啟動數據庫服務并設置開機自啟 5.檢測MySQL當前狀態 6.配置文件修改 二、基本操作指令 1.登陸MySQL 2.創建用戶&修改用戶密碼 3.查看版本 4.退出MySQL 5.停止MySQL 6.數據…

(C++)任務管理系統(正式版)(迭代器)(list列表基礎教程)(STL基礎知識)

源代碼&#xff1a;#include <iostream> #include <list> #include <string>using namespace std;void menu(){cout<<"\n 任務管理系統 "<<endl;cout<<"1.添加普通任務"<<endl;cout<<"2.添加緊急任務…

創建uniapp項目引入uni-id用戶體系使用beforeRegister鉤子創建默認昵稱

需求描述 基于uniCloud開發項目&#xff0c;通常會使用用戶體系&#xff0c;uni-id就是基于uniCloud的用戶體系&#xff0c;滿足常規需要的賬號密碼注冊、登錄&#xff0c;微信登錄等快捷方式&#xff0c;如果使用uni-id自帶的uni-id-pages插件&#xff0c;賬號密碼注冊的話&a…

Opencv---深度學習開發

在OpenCV中進行深度學習開發&#xff0c;主要圍繞其dnn模塊展開&#xff0c;該模塊支持加載預訓練模型、預處理輸入數據、執行推理計算以及解析輸出結果。本文講解基于OpenCV進行深度學習開發的基本流程。 一、準備工作 在開始開發前&#xff0c;需完成環境配置和資源準備&…

【C++11】右值引用詳解

文章目錄前言1. 左、右值的概念1.1 左值1.2 右值1.3 右值引用2. 右值引用的價值和使用場景2.1 左值引用的價值和缺陷2.2 右值引用的價值和使用場景2.3 小結3. 完美轉發4. 類的移動構造和移動賦值前言 在C11之前&#xff0c;面對C11之前出現的臨時對象的傳參構造&#xff0c;都…

如何用自指理解世界

自指即自我指涉&#xff0c;即自己的描述關聯到了自己&#xff0c;典型例子是“這句話是假話”這個悖論。人類對自指的研究由來已久&#xff0c;很多概念、定理都與之相關&#xff0c;由于它的巧妙性&#xff0c;很多學者對其展開了深入研究&#xff0c;并且認為自指是理解宇宙…

Next.js 實戰筆記 2.0:深入 App Router 高階特性與布局解構

Next.js 實戰筆記 2.0&#xff1a;深入 App Router 高階特性與布局解構 上一篇筆記&#xff1a; Next.js 實戰筆記 1.0&#xff1a;架構重構與 App Router 核心機制詳解 上篇筆記主要回顧了一些 Next12 到 Next15 的一些變化&#xff0c;這里繼續學習/復習一些已有或者是新的…

TCP 傳輸時 sk_buff 的 clone 和 unclone

周一有位朋友咨詢個問題&#xff0c;問題本身不重要&#xff0c;但牽扯出的細節卻是非常有趣。 Linux 內核協議棧的 skb 設計非常高效和精巧&#xff0c;多個 skb 可以指向同一塊 data&#xff0c;這就是 clone&#xff0c;當 data 不止一個 skb 指示時&#xff0c;任何一個 s…