切換語言為:簡體

適用於 SpringBoot 專案的統一響應結果處理開源jar包,程式設計師拒絕重複勞動!

  • 爱糖宝
  • 2024-05-19
  • 2060
  • 0
  • 0

簡介

Graceful Response是一個Spring Boot技術棧下的優雅響應處理器,提供一站式統一返回值封裝、全域性異常處理、自定義異常錯誤碼等功能,使用Graceful Response進行web介面開發不僅可以節省大量的時間,還可以提高程式碼質量,使程式碼邏輯更清晰。

強烈推薦你花3分鐘學會它!

本專案案例工程程式碼:https://github.com/feiniaojin/graceful-response-example.git ,注意選擇最新版本的分支。

Spring Boot版本

Graceful Response版本 graceful-response-example分支
2.x
3.2.1-boot2
3.2.0-boot2
3.x
3.2.1-boot3
3.2.0-boot3

Spring Boot介面開發現狀

目前,業界使用Spring Boot進行介面開發時,往往存在效率底下、重複勞動、可讀性差等問題。以下虛擬碼相信大家非常熟悉,我們大部分專案的Controller介面都是這樣的。

@Controller
public class Controller {
    @GetMapping("/query")
    @ResponseBody
    public Response query(Map<String, Object> paramMap) {
        Response res = new Response();
        try {
            //1.校驗params引數合法性,包括非空校驗、長度校驗等
            if (illegal(paramMap)) {
                res.setCode(1);
                res.setMsg("error");
                return res;
            }
            //2.呼叫Service的一系列操作,得到查詢結果
            Object data = service.query(params);
            //3.將操作結果設定到res物件中
            res.setData(data);
            res.setCode(0);
            res.setMsg("ok");
            return res;
        } catch (Exception e) {
            //4.異常處理:一堆醜陋的try...catch,如果有錯誤碼的,還需要手工填充錯誤碼
            res.setCode(1);
            res.setMsg("error");
            return res;
        }
    }
}

這段虛擬碼存在什麼樣的問題呢?

第一個問題,效率低下。 Controller層的程式碼應該儘量簡潔,上面的虛擬碼其實只是爲了將資料查詢的結果進行封裝,使其以統一的格式進行返回。例如以下格式的響應體:

{
  "code": 0,
  "msg": "ok",
  "data": {
    "id": 1,
    "name": "username"
  }
}

查詢過程中如果發生異常,需要在Controller進行手工捕獲,根據捕獲的異常人工地設定錯誤碼,當然,也用同樣的格式封裝錯誤碼進行返回。

可以看到,除了呼叫service層的query方法這一行,其他大部分的程式碼都執行進行結果的封裝,大量的冗餘、低價值的程式碼導致我們的開發活動效率很低。

第二個問題,重複勞動。 以上捕獲異常、封裝執行結果的操作,每個介面都會進行一次,因此造成大量重複勞動。

第三個問題,可讀性低。 上面的核心程式碼被淹沒在許多冗餘程式碼中,很難閱讀,如同大海撈針。

我們可以透過Graceful Response這個元件解決這樣的問題。

快速入門

引入Graceful Response元件

Graceful Response已釋出至maven中央倉庫,我們可以直接引入到專案中。

maven依賴如下:

<dependency>
    <groupId>com.feiniaojin</groupId>
    <artifactId>graceful-response</artifactId>
    <version>{latest.version}</version>
</dependency>

Spring Boot版本

Graceful Response最新版本
2.x
3.2.1-boot2
3.x
3.2.1-boot3

啟用Graceful Response

在啟動類中引入@EnableGracefulResponse註解,即可啟用Graceful Response元件。

@EnableGracefulResponse
@SpringBootApplication
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }
}

Controller層

引入Graceful Response後,我們不需要再手工進行查詢結果的封裝,直接返回實際結果即可,Graceful Response會自動完成封裝的操作。

Controller層示例如下。

@Controller
public class Controller {
    @RequestMapping("/get")
    @ResponseBody
    public UserInfoView get(Long id) {
        log.info("id={}", id);
        return UserInfoView.builder().id(id).name("name" + id).build();
    }
}

在示例程式碼中,Controller層的方法直接返回了UserInfoView物件,沒有進行封裝的操作,但經過Graceful Response處理後,我們還是得到了以下的響應結果。

{
  "status": {
    "code": "0",
    "msg": "ok"
  },
  "payload": {
    "id": 1,
    "name": "name1"
  }
}

而對於命令操作(Command)儘量不返回資料,因此command操作的方法的返回值應該是void,Graceful Response對於對於返回值型別void的方法,也會自動進行封裝。

public class Controller {
    @RequestMapping("/command")
    @ResponseBody
    public void command() {
        //業務操作
    }
}

成功呼叫該介面,將得到:

{
  "status": {
    "code": "200",
    "msg": "success"
  },
  "payload": {}
}

Service層

在引入Graceful Response前,有的開發者在定義Service層的方法時,爲了在介面中返回異常碼,乾脆直接將Service層方法定義為Response,淹沒了方法的正常返回值。

Response的程式碼如下。

//lombok註解

@Data
public class Response {
    private String code;
    private String msg;
    private Object data;
}

直接返回Response的Service層方法:

/**
 * 直接返回Reponse的Service
 * 不規範
 */
public interface Service {
    public Reponse commandMethod(Command command);
}

Graceful Response引入@ExceptionMapper註解,透過該註解將異常和錯誤碼關聯起來,這樣Service方法就不需要再維護Response的響應碼了,直接丟擲業務異常,由Graceful Response進行異常和響應碼的關聯。

@ExceptionMapper的用法如下。

/**
 * NotFoundException的定義,使用@ExceptionMapper註解修飾
 * code:代表介面的異常碼
 * msg:代表介面的異常提示
 */
@ExceptionMapper(code = "1404", msg = "找不到物件")
public class NotFoundException extends RuntimeException {
}

Service介面定義:

public interface QueryService {
    UserInfoView queryOne(Query query);
}

Service介面實現:

public class QueryServiceImpl implements QueryService {
    @Resource
    private UserInfoMapper mapper;
    public UserInfoView queryOne(Query query) {
        UserInfo userInfo = mapper.findOne(query.getId());
        if (Objects.isNull(userInfo)) {
            //這裏直接拋自定義異常
            throw new NotFoundException();
        }
        //……後續業務操作
    }
}

當Service層的queryOne方法丟擲NotFoundException時,Graceful Response會進行異常捕獲,並將NotFoundException對應的異常碼和異常資訊封裝到統一的響應物件中,最終介面返回以下JSON。

{
  "status": {
    "code": "1404",
    "msg": "找不到物件"
  },
  "payload": {}
}

引數校驗

Graceful Response對JSR-303資料校驗規範和Hibernate Validator進行了增強,Graceful Response自身不提供引數校驗的功能,但是使用者使用了Hibernate Validator後,Graceful Response可以透過@ValidationStatusCode註解為引數校驗結果提供響應碼,並將其統一封裝返回。

例如以下的UserInfoQuery。

@Data
public class UserInfoQuery {
    @NotNull(message = "userName is null !")
    @Length(min = 6, max = 12)
    @ValidationStatusCode(code = "520")
    private String userName;
}

UserInfoQuery物件中定義了@NotNull和@Length兩個校驗規則,在未引入Graceful Response的情況下,會直接丟擲異常;

在引入Graceful Response但是沒有加入@ValidationStatusCode註解的情況下,會以預設的錯誤碼進行返回;

在上面的UserInfoQuery中由於使用了@ValidationStatusCode註解,並指定異常碼為520,則當userName欄位任意校驗不透過時,都會使用異常碼520進行返回,如下。

{
  "status": {
    "code": "520",
    "msg": "userName is null !"
  },
  "payload": {}
}

而對於Controller層直接校驗方法入參的場景,Graceful Response也進行了增強,如以下Controller。

public class Controller {
    @RequestMapping("/validateMethodParam")
    @ResponseBody
    @ValidationStatusCode(code = "1314")
    public void validateMethodParam(
            @NotNull(message = "userId不能為空") Long userId,
            @NotNull(message = "userName不能為空") Long userName) {
        //省略業務邏輯
    }
}

如果該方法入參校驗觸發了userId和userName的校驗異常,將以錯誤碼1314進行返回,如下。

{
  "status": {
    "code": "1314",
    "msg": "userId不能為空"
  },
  "payload": {}
}

自定義Response格式

Graceful Response內建了兩種風格的響應格式,並透過graceful-response.response-style進行配置。

graceful-response.response-style=0,或者不配置(預設情況),將以以下的格式進行返回:

{
  "status": {
    "code": 1007,
    "msg": "有內鬼,終止交易"
  },
  "payload": {
  }
}

graceful-response.response-style=1,將以以下的格式進行返回:

{
  "code": "1404",
  "msg": "not found",
  "data": {
  }
}

如果這兩種格式均不滿足業務需要,Graceful Response也支援使用者自定義響應體,關於自定義響應體的技術實現,請到自定義Response格式進行了解。

本專案提供的進階功能,包括

  • 第三方元件汽車(Swagger、執行器等)

  • 自定義響應

  • 異常請求放行

  • 異常別名

  • 常用配置項

專案地址

https://github.com/feiniaojin/graceful-response

0則評論

您的電子郵件等資訊不會被公開,以下所有項目均必填

OK! You can skip this field.