javascript
boot返回码规范 spring_SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势
200105-SpringBoot 系列 web 篇之自定義返回 Http Code 的 n 種姿勢(shì)
雖然 http 的提供了一整套完整、定義明確的狀態(tài)碼,但實(shí)際的業(yè)務(wù)支持中,后端并不總會(huì)遵守這套規(guī)則,更多的是在返回結(jié)果中,加一個(gè) code 字段來(lái)自定義業(yè)務(wù)狀態(tài),即便是后端 5xx 了,返回給前端的 http code 依然是 200
那么如果我想遵守 http 的規(guī)范,不同的 case 返回不同的 http code 在 Spring 中可以做呢?
本文將介紹四種設(shè)置返回的 HTTP CODE 的方式
- @ResponseStatus 注解方式
- HttpServletResponse#sendError
- HttpServletResponse#setStatus
- ResponseEntity
I. 返回 Http Code 的 n 種姿勢(shì)
0. 環(huán)境
進(jìn)入正文之前,先創(chuàng)建一個(gè) SpringBoot 項(xiàng)目,本文示例所有版本為 spring-boot.2.1.2.RELEASE
(需要測(cè)試的小伙伴,本機(jī)創(chuàng)建一個(gè) maven 項(xiàng)目,在pom.xml文件中,拷貝下面的配置即可)
org.springframework.boot spring-boot-starter-parent 2.2.1.RELEASEUTF-8UTF-81.8org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-maven-plugin spring-snapshotsSpring Snapshotshttps://repo.spring.io/libs-snapshot-localtruespring-milestonesSpring Milestoneshttps://repo.spring.io/libs-milestone-localfalsespring-releasesSpring Releaseshttps://repo.spring.io/libs-release-localfalse下面所有的方法都放在 ErrorCodeRest 這個(gè)類中
@RestController@RequestMapping(path = "code")public class ErrorCodeRest {}1. ResponseStatus 使用姿勢(shì)
通過(guò)注解@ResponseStatus,來(lái)指定返回的 http code, 一般來(lái)說(shuō),使用它有兩種姿勢(shì),一個(gè)是直接加在方法上,一個(gè)是加在異常類上
a. 裝飾方法
直接在方法上添加注解,并制定對(duì)應(yīng)的 code
/** * 注解方式,只支持標(biāo)準(zhǔn)http狀態(tài)碼 * * @return */@GetMapping("ano")@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "請(qǐng)求參數(shù)異常!")public String ano() { return "{"code": 400, "msg": "bad request!"}";}實(shí)測(cè)一下,返回結(jié)果如下
? ~ curl 'http://127.0.0.1:8080/code/ano' -iHTTP/1.1 400Content-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedDate: Sun, 05 Jan 2020 01:29:04 GMTConnection: close{"timestamp":"2020-01-05T01:29:04.673+0000","status":400,"error":"Bad Request","message":"請(qǐng)求參數(shù)異常!","path":"/code/ano"}%當(dāng)我們發(fā)起請(qǐng)求時(shí),返回的狀態(tài)碼為 400,返回的數(shù)據(jù)為 springboot 默認(rèn)的錯(cuò)誤信息格式
雖然上面這種使用姿勢(shì)可以設(shè)置 http code,但是這種使用姿勢(shì)有什么意義呢?
如果看過(guò) web 系列教程中的:SpringBoot 系列教程 web 篇之全局異常處理 可能就會(huì)有一些映象,配合@ExceptionHandler來(lái)根據(jù)異常返回對(duì)應(yīng)的狀態(tài)碼
一個(gè)推薦的使用姿勢(shì),下面表示當(dāng)你的業(yè)務(wù)邏輯中出現(xiàn)數(shù)組越界時(shí),返回 500 的狀態(tài)碼以及完整的堆棧信息
@ResponseBody@ExceptionHandler(value = ArrayIndexOutOfBoundsException.class)@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)public String handleArrayIndexOutBounds(HttpServletRequest request, HttpServletResponse response, ArrayIndexOutOfBoundsException e) throws IOException { log.info("array index out conf!"); return "aryIndexOutOfBounds: " + getThrowableStackInfo(e);}b. 裝飾異常類
另外一種使用姿勢(shì)就是直接裝飾在異常類上,然后當(dāng)你的業(yè)務(wù)代碼中,拋出特定的異常類,返回的 httpcode 就會(huì)設(shè)置為注解中的值
/** * 異常類 + 注解方式,只支持標(biāo)準(zhǔn)http狀態(tài)碼 * * @return */@GetMapping("exception/500")public String serverException() { throw new ServerException("內(nèi)部異常哦");}@GetMapping("exception/400")public String clientException() { throw new ClientException("客戶端異常哦");}@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR, reason = "服務(wù)器失聯(lián)了,請(qǐng)到月球上呼叫試試~~")public static class ServerException extends RuntimeException { public ServerException(String message) { super(message); }}@ResponseStatus(code = HttpStatus.BAD_REQUEST, reason = "老哥,你的請(qǐng)求有問(wèn)題~~")public static class ClientException extends RuntimeException { public ClientException(String message) { super(message); }}測(cè)試結(jié)果如下,在異常類上添加注解的方式,優(yōu)點(diǎn)在于不需要配合@ExceptionHandler寫額外的邏輯了;缺點(diǎn)則在于需要定義很多的自定義異常類型
? ~ curl 'http://127.0.0.1:8080/code/exception/400' -iHTTP/1.1 400Content-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedDate: Sun, 05 Jan 2020 01:37:07 GMTConnection: close{"timestamp":"2020-01-05T01:37:07.662+0000","status":400,"error":"Bad Request","message":"老哥,你的請(qǐng)求有問(wèn)題~~","path":"/code/exception/400"}%? ~ curl 'http://127.0.0.1:8080/code/exception/500' -iHTTP/1.1 500Content-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedDate: Sun, 05 Jan 2020 01:37:09 GMTConnection: close{"timestamp":"2020-01-05T01:37:09.389+0000","status":500,"error":"Internal Server Error","message":"服務(wù)器失聯(lián)了,請(qǐng)到月球上呼叫試試~~","path":"/code/exception/500"}%注意
- ResponseStatus 注解的使用姿勢(shì),只支持標(biāo)準(zhǔn)的 Http Code(必須是枚舉類org.springframework.http.HttpStatus)
2. ResponseEntity
這種使用姿勢(shì)就比較簡(jiǎn)單了,方法的返回結(jié)果必須是ResponseEntity,下面給出兩個(gè)實(shí)際的 case
@GetMapping("401")public ResponseEntity _401() { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("{"code": 401, "msg": "未授權(quán)!"}");}@GetMapping("451")public ResponseEntity _451() { return ResponseEntity.status(451).body("{"code": 451, "msg": "自定義異常!"}");}實(shí)測(cè)結(jié)果
? ~ curl 'http://127.0.0.1:8080/code/401' -iHTTP/1.1 401Content-Type: text/plain;charset=UTF-8Content-Length: 34Date: Sun, 05 Jan 2020 01:40:10 GMT{"code": 401, "msg": "未授權(quán)!"}? ~ curl 'http://127.0.0.1:8080/code/451' -iHTTP/1.1 451Content-Type: text/plain;charset=UTF-8Content-Length: 40Date: Sun, 05 Jan 2020 01:40:19 GMT{"code": 451, "msg": "自定義異常!"}從上面的使用實(shí)例上看,可以知道這種使用方式,不僅僅支持標(biāo)準(zhǔn)的 http code,也支持自定義的 code(如返回 code 451)
3. HttpServletResponse
這種使用姿勢(shì)則是直接操作HttpServletResponse對(duì)象,手動(dòng)錄入返回的結(jié)果
a. setStatus
/** * response.setStatus 支持自定義http code,并可以返回結(jié)果 * * @param response * @return */@GetMapping("525")public String _525(HttpServletResponse response) { response.setStatus(525); return "{"code": 525, "msg": "自定義錯(cuò)誤碼 525!"}";}輸出結(jié)果
? ~ curl 'http://127.0.0.1:8080/code/525' -iHTTP/1.1 525Content-Type: text/plain;charset=UTF-8Content-Length: 47Date: Sun, 05 Jan 2020 01:45:38 GMT{"code": 525, "msg": "自定義錯(cuò)誤碼 525!"}%使用方式比較簡(jiǎn)單,直接設(shè)置 status 即可,支持自定義的 Http Code 返回
b. sendError
使用這種姿勢(shì)的時(shí)候需要注意一下,只支持標(biāo)準(zhǔn)的 http code,而且 response body 中不會(huì)有你的業(yè)務(wù)返回?cái)?shù)據(jù),如
/** * send error 方式,只支持標(biāo)準(zhǔn)http狀態(tài)碼; 且不會(huì)帶上返回的結(jié)果 * * @param response * @return * @throws IOException */@GetMapping("410")public String _410(HttpServletResponse response) throws IOException { response.sendError(410, "send 410"); return "{"code": 410, "msg": "Gone 410!"}";}@GetMapping("460")public String _460(HttpServletResponse response) throws IOException { response.sendError(460, "send 460"); return "{"code": 460, "msg": "Gone 460!"}";}輸出結(jié)果
? ~ curl 'http://127.0.0.1:8080/code/410' -iHTTP/1.1 410Content-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedDate: Sun, 05 Jan 2020 01:47:52 GMT{"timestamp":"2020-01-05T01:47:52.300+0000","status":410,"error":"Gone","message":"send 410","path":"/code/410"}%? ~ curl 'http://127.0.0.1:8080/code/460' -iHTTP/1.1 500Content-Type: application/json;charset=UTF-8Transfer-Encoding: chunkedDate: Sun, 05 Jan 2020 01:47:54 GMTConnection: close{"timestamp":"2020-01-05T01:47:54.719+0000","status":460,"error":"Http Status 460","message":"send 460","path":"/code/460"}%從上面的 case 也可以看出,當(dāng)我們使用 send error 時(shí),如果是標(biāo)準(zhǔn)的 http code,會(huì)設(shè)置對(duì)響應(yīng)頭;如果是自定義的不被識(shí)別的 code,那么返回的 http code 是 500
4, 小結(jié)
上面介紹了幾種常見(jiàn)的設(shè)置響應(yīng) http code 的姿勢(shì),下面小結(jié)一下使用時(shí)的注意事項(xiàng)
ResponseStatus
- 只支持標(biāo)準(zhǔn)的 http code
- 裝飾自定義異常類,使用時(shí)拋出對(duì)應(yīng)的異常類,從而達(dá)到設(shè)置響應(yīng) code 的效果 缺點(diǎn)對(duì)非可控的異常類不可用
- 結(jié)合@ExceptionHandler,用來(lái)裝飾方法
ResponseEntity
形如:
return ResponseEntity.status(451).body("{"code": 451, "msg": "自定義異常!"}");- 我個(gè)人感覺(jué)是最強(qiáng)大的使用姿勢(shì),就是寫起來(lái)沒(méi)有那么簡(jiǎn)潔
- 支持自定義 code,支持設(shè)置 response body
HttpServletResponse
- setStatus: 設(shè)置響應(yīng) code,支持自定義 code,支持返回 response body
- sendError: 只支持標(biāo)準(zhǔn)的 http code,如果傳入自定義的 code,返回的 http code 會(huì)是 500
II. 其他
項(xiàng)目源碼
- 工程:https://github.com/liuyueyi/spring-boot-demo[1]
- 項(xiàng)目:https://github.com/liuyueyi/spring-boot-demo/blob/master/spring-boot/207-web-response[2]
1. 一灰灰 Blog
盡信書則不如,以上內(nèi)容,純屬一家之言,因個(gè)人能力有限,難免有疏漏和錯(cuò)誤之處,如發(fā)現(xiàn) bug 或者有更好的建議,歡迎批評(píng)指正,不吝感激
下面一灰灰的個(gè)人博客,記錄所有學(xué)習(xí)和工作中的博文,歡迎大家前去逛逛
- 一灰灰 Blog 個(gè)人博客 https://blog.hhui.top[3]
- 一灰灰 Blog-Spring 專題博客 http://spring.hhui.top[4]
總結(jié)
以上是生活随笔為你收集整理的boot返回码规范 spring_SpringBoot 系列 web 篇之自定义返回 Http Code 的 n 种姿势的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: int类型存小数 mysql_MySQL
- 下一篇: sqlserver 根据数组排序_看动画