国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

年輕人不講武德,竟然重構(gòu)出這么優(yōu)雅后臺(tái) API 接口

開發(fā) 前端
最近偶然間在看到 Spring 官方文檔的時(shí)候,新學(xué)到一個(gè)注解 @ControllerAdvice,并且成功使用這個(gè)注解重構(gòu)我們項(xiàng)目的對(duì)外 API 接口,去除繁瑣的重復(fù)代碼,使其開發(fā)更加優(yōu)雅。

[[353770]]

 本文轉(zhuǎn)載自微信公眾號(hào)「Java極客技術(shù)」,作者鴨血粉絲 。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java極客技術(shù)公眾號(hào)。   

 Hello,早上好,我是阿粉~

最近偶然間在看到 Spring 官方文檔的時(shí)候,新學(xué)到一個(gè)注解 @ControllerAdvice,并且成功使用這個(gè)注解重構(gòu)我們項(xiàng)目的對(duì)外 API 接口,去除繁瑣的重復(fù)代碼,使其開發(fā)更加優(yōu)雅。

展示具體重構(gòu)代碼之前,我們先來看下原先對(duì)外 API 接口是如何開發(fā)的。

這個(gè) API 接口主要是用來與我們 APP 交互,這個(gè)過程我們統(tǒng)一定義一個(gè)交互協(xié)議,APP 端與后臺(tái) API 接口統(tǒng)一都使用 JSON 格式。

另外后臺(tái) API 接口對(duì) APP 返回時(shí),統(tǒng)一一些錯(cuò)誤碼,APP 端需要根據(jù)相應(yīng)錯(cuò)誤碼,在頁(yè)面彈出一些提示。

下面展示一個(gè)查詢用戶信息返回的接口數(shù)據(jù):

  1.     "code""000000"
  2.     "msg""success"
  3.     "result": { 
  4.         "id""1"
  5.         "name""test" 
  6.     } 

code代表對(duì)外的錯(cuò)誤碼,msg代表錯(cuò)誤信息,result代表具體返回信息。

前端 APP 獲取這個(gè)返回信息,首先判斷接口返回 code是否為 「000000」,如果是代表查詢成功,然后獲取 result 信息作出相應(yīng)的展示。否則,直接彈出相應(yīng)的錯(cuò)誤信息。

重構(gòu)之前

下面我們來看下,重構(gòu)之前的,后臺(tái) API 層的如何編碼。

  1. /** 
  2.  * V1 版本 
  3.  * 
  4.  * @return 
  5.  */ 
  6. @RequestMapping("testv1"
  7. public APIResult testv1() { 
  8.     try { 
  9.         User user = new User(); 
  10.         user.setId("1"); 
  11.         user.setName("test"); 
  12.         return APIResult.success(user); 
  13.     } catch (APPException e) { 
  14.         log.error("內(nèi)部異常", e); 
  15.         return APIResult.error(e.getCode(), e.getMsg()); 
  16.     } catch (Exception e) { 
  17.         log.error("系統(tǒng)異常", e); 
  18.         return APIResult.error(RetCodeEnum.FAILED); 
  19.     } 

上面的代碼其實(shí)很簡(jiǎn)單,內(nèi)部統(tǒng)一封裝了一個(gè)工具類 APIResult,然后用其包裝具體的結(jié)果。

  1. @Data 
  2. public class APIResult<T> implements Serializable { 
  3.  
  4.     private static final long serialVersionUID = 4747774542107711845L; 
  5.  
  6.     private String code; 
  7.  
  8.     private String msg; 
  9.  
  10.     private T result; 
  11.  
  12.  
  13.     public static <T> APIResult success(T result) { 
  14.         APIResult apiResult = new APIResult(); 
  15.         apiResult.setResult(result); 
  16.         apiResult.setCode("000000"); 
  17.         apiResult.setMsg("success"); 
  18.         return apiResult; 
  19.     } 
  20.  
  21.     public static APIResult error(String code, String msg) { 
  22.         APIResult apiResult = new APIResult(); 
  23.         apiResult.setCode(code); 
  24.         apiResult.setMsg(msg); 
  25.         return apiResult; 
  26.     } 
  27.  
  28.     public static APIResult error(RetCodeEnum codeEnum) { 
  29.         APIResult apiResult = new APIResult(); 
  30.         apiResult.setCode(codeEnum.getCode()); 
  31.         apiResult.setMsg(codeEnum.getMsg()); 
  32.         return apiResult; 
  33.     } 

除了這個(gè)以外,還定義一個(gè)異常對(duì)象 APPException,用來統(tǒng)一包裝內(nèi)部的各種異常。

上面的代碼很簡(jiǎn)單,但是呢可以說比較繁瑣,重復(fù)代碼也比較多,每個(gè)接口都需要使用 try...catch 包裝,然后使用 APIResult包括正常的返回信息與錯(cuò)誤信息。

第二呢,接口對(duì)象只能返回 APIResult,真實(shí)業(yè)務(wù)對(duì)象只能隱藏在 APIResult中。這樣不太優(yōu)雅,另外不能很直觀知道真實(shí)業(yè)務(wù)對(duì)象。

重構(gòu)之后

下面我們開始重構(gòu)上面的代碼,主要目的是去除重復(fù)的那一坨try...catch 代碼。

這次重構(gòu)我們需要使用Spring 注解 @ControllerAdvice以及 ResponseBodyAdvice,我們先來看下重構(gòu)的代碼。

ps: ResponseBodyAdvice來自 Spring 4.2 API,如果各位同學(xué)需要使用這個(gè)的話,可能需要升級(jí) Spring 版本。

改寫返回信息

首先我們需要實(shí)現(xiàn) ResponseBodyAdvice,實(shí)現(xiàn)我們自己的處理類。

  1. @ControllerAdvice 
  2. public class CustomResponseAdvice implements ResponseBodyAdvice { 
  3.     /** 
  4.      * 是否需要處理返回結(jié)果 
  5.      * @param methodParameter 
  6.      * @param aClass 
  7.      * @return 
  8.      */ 
  9.     @Override 
  10.     public boolean supports(MethodParameter methodParameter, Class aClass) { 
  11.         System.out.println("In supports() method of " + getClass().getSimpleName()); 
  12.         return true
  13.     } 
  14.  
  15.     /** 
  16.      * 處理返回結(jié)果 
  17.      * @param body 
  18.      * @param methodParameter 
  19.      * @param mediaType 
  20.      * @param aClass 
  21.      * @param serverHttpRequest 
  22.      * @param serverHttpResponse 
  23.      * @return 
  24.      */ 
  25.     @Override 
  26.     public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { 
  27.         System.out.println("In beforeBodyWrite() method of " + getClass().getSimpleName()); 
  28.         if (body instanceof APIResult) { 
  29.             return body; 
  30.         } 
  31.         return APIResult.success(body); 
  32.     } 

實(shí)現(xiàn)上面的接口,我們就可以在 beforeBodyWrite方法里,修改返回結(jié)果了。

上面代碼中,只是簡(jiǎn)單使用 APIResult包裝了返回結(jié)果,然后返回。其實(shí)我們還可以在此增加一些額外邏輯,比如說如接口返回信息由加密的需求,我們可以在這一層統(tǒng)一加密。

另外,這里判斷一下 body 是否 APIResult類,如果是就直接返回,不做修改。

這么做一來兼容之前的老接口,這是因?yàn)槟J(rèn)情況下,我們自己實(shí)現(xiàn)的 CustomResponseAdvice類,將會(huì)對(duì)所有的 Controller 生效。

如果不做判斷,以前的老接返回就會(huì)被包裝了兩層 APIResul,影響 APP 解析。

除此之外,如果大家擔(dān)心這個(gè)修改對(duì)以前的老接口有影響的話,可以使用下面的方式,只對(duì)指定的方法生效。

首先自定義一個(gè)注解,比如說:

  1. @Target({ElementType.TYPE, ElementType.METHOD}) 
  2. @Retention(RetentionPolicy.RUNTIME) 
  3. @Documented 
  4. public @interface CustomResponse { 

然后將其標(biāo)注在需要改動(dòng)的方法中,然后我們?cè)?ResponseBodyAdvice#supports中判斷具體方法上有沒有自定義注解 CustomResponse,如果存在,返回 true,這就代表最后將會(huì)修改返回類。如果不存在,則返回 false,那么就會(huì)跟以前流程一樣。

  1. /** 
  2.  * 是否需要處理返回結(jié)果 
  3.  * 
  4.  * @param methodParameter 
  5.  * @param aClass 
  6.  * @return 
  7.  */ 
  8. @Override 
  9. public boolean supports(MethodParameter methodParameter, Class aClass) { 
  10.     System.out.println("In supports() method of " + getClass().getSimpleName()); 
  11.     Method method = methodParameter.getMethod(); 
  12.     return method.isAnnotationPresent(CustomResponse.class); 

全局異常處理

上面的代碼重構(gòu)之后,將重復(fù)代碼抽取了出來,整體的代碼就剩下我們的業(yè)務(wù)邏輯,這樣就變得非常簡(jiǎn)潔優(yōu)雅。

不過,上面的重構(gòu)的代碼,還是存在問題,主要是異常的處理。

如果上面的業(yè)務(wù)代碼拋出了異常,那么接口將會(huì)返回堆棧錯(cuò)誤信息,而不是我們定義的錯(cuò)誤信息。所以下面我們這個(gè),再次優(yōu)化一下。

這次我們主要需要使用 @ExceptionHandler注解,這個(gè)注解需要與 @ControllerAdvice 一起使用。

  1. @Slf4j 
  2. @ControllerAdvice 
  3. public class CustomExceptionHandler { 
  4.  
  5.     @ExceptionHandler(Exception.class) 
  6.     @ResponseBody 
  7.     public APIResult handleException(Exception e) { 
  8.         log.error("系統(tǒng)異常", e); 
  9.         return APIResult.error(RetCodeEnum.FAILED); 
  10.     } 
  11.  
  12.     @ExceptionHandler(APPException.class) 
  13.     @ResponseBody 
  14.     public APIResult handleAPPException(APPException e) { 
  15.         log.error("內(nèi)部異常", e); 
  16.         return APIResult.error(e.getCode(), e.getMsg()); 
  17.     } 
  18.  

使用這個(gè) @ExceptionHandler,將會(huì)攔截相應(yīng)的異常,然后將會(huì)調(diào)用的相應(yīng)方法處理異常。這里我們就使用 APIResult包裝一些錯(cuò)誤信息返回。

總結(jié)

我們可以使用 @ControllerAdvice加 ResponseBodyAdvice 攔截返回結(jié)果,統(tǒng)一做出一些修改。這樣就可以使用的業(yè)務(wù)代碼非常簡(jiǎn)潔,優(yōu)雅。

另外,針對(duì)業(yè)務(wù)代碼的中,我們可以使用 @ExceptionHandler注解,統(tǒng)一做一個(gè)全局異常處理,這樣就可以無縫的跟 ResponseBodyAdvice結(jié)合。

不過這里需要一點(diǎn),我們實(shí)現(xiàn)的 ResponseBodyAdvice 類,一定需要跟 @ControllerAdvice配合一起使用哦,至于具體原因,下篇文章阿粉分析原來的時(shí)候,再具體解釋哦。敬請(qǐng)期待哦~

 

責(zé)任編輯:武曉燕 來源: Java極客技術(shù)
相關(guān)推薦

2021-07-06 21:37:05

索引SQL數(shù)據(jù)

2021-05-31 09:03:12

算法數(shù)據(jù)技術(shù)

2021-01-27 09:19:44

MySQL數(shù)據(jù)優(yōu)化器

2020-12-07 08:04:39

CTO中年公司

2021-05-26 05:40:32

加密勒索軟件攻擊

2020-12-25 11:37:32

DDoS攻擊信用卡黑客

2022-01-13 06:49:23

開源項(xiàng)目刪庫(kù)

2019-09-17 16:04:17

戴爾

2021-09-14 11:57:01

雙重勒索勒索軟件黑客攻擊

2021-01-29 14:35:41

代碼開發(fā)服務(wù)器

2021-02-28 07:52:24

蠕蟲數(shù)據(jù)金絲雀

2020-11-05 14:48:29

AI人工智能互聯(lián)網(wǎng)

2020-10-09 09:28:43

互聯(lián)網(wǎng)數(shù)據(jù)技術(shù)

2019-04-01 15:28:20

996互聯(lián)網(wǎng)ICU

2020-12-03 18:18:46

微信表情下回

2012-09-03 14:26:50

云計(jì)算亞馬遜AWS

2020-05-20 15:37:43

VR虛擬現(xiàn)實(shí)年輕人

2021-03-01 19:11:10

大數(shù)據(jù)技術(shù)金融

2010-08-20 10:34:29

施密特
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

性猛交ⅹ×××乱大交| 粉嫩av一区二区三区天美传媒| 青青操视频在线| 成人精品视频一区二区三区| 亚洲综合在线做性| 日本免费一区二区六区| 国产精品欧美久久久久无广告| 欧美日韩在线观看一区二区三区| 久久gogo国模啪啪裸体| 日韩美女一区二区三区四区| 欧美偷拍视频| 五月天婷婷综合| 国外亚洲成av人片在线观看| caoporn国产精品| 亚洲国产欧美一区二区三区不卡| 日韩精品免费| 欧美精品在线免费播放| 国产精品久久乐| 欧美精品一区二区三区在线| 北条麻妃在线| 在线观看精品一区| 91在线免费看| 欧美日韩高清一区二区| 天天在线视频色| 91超碰这里只有精品国产| 国产精品视频专区| 日韩理论电影院| 国产精品久久久久久久久久三级| 自拍偷拍精品| 国产福利精品视频| 日韩av专区| 日韩在线免费观看视频| 懂色aⅴ精品一区二区三区| 免费91在线视频| 成人三级视频| 97在线电影| 国内成人精品2018免费看| 国产免费一区二区视频| 亚洲欧洲精品天堂一级| 国家队第一季免费高清在线观看| 4hu四虎永久在线影院成人| 国产经典三级在线| 久久天堂电影网| 欧美日韩一区二区综合| 欧美综合国产精品久久丁香| 免费大片黄在线观看视频网站| 国产大片一区二区| 国产精品电影网| 黄色的视频在线免费观看| 亚洲国产精品一区制服丝袜| 99re视频这里只有精品| 国产精品国产一区二区| 亚洲深夜影院| 黄色一级大片免费| 玉米视频成人免费看| 美女网站在线| 日韩在线视频播放| 欧美国产小视频| 国产精品对白刺激| 美女福利一区| 日韩欧美三级电影| 国产精品白丝在线| 超碰成人av| 国产精品免费一区二区三区在线观看 | www视频在线观看| 欧美一级视频一区二区| 国产精品系列在线播放| 日韩欧美电影在线观看| 国产91精品久| 粉嫩av亚洲一区二区图片| 中文字幕一区免费| 国产成人精品综合久久久| 性一交一乱一区二区洋洋av| 99re精彩视频| 少妇激情综合网| 国产成人av影院| 亚洲欧美在线成人| 欧美裸体男粗大视频在线观看| 久久要要av| 国产欧美自拍视频| 日韩一区二区免费高清| 亚洲综合丁香| 国产1区在线| 国产在线一区二| 欧美日韩aaaaa| 国产精品麻豆成人av电影艾秋| 欧美男女爱爱视频| 91精品欧美综合在线观看最新| 久久gogo国模啪啪裸体| 国产私拍一区| 欧美www视频| 国产精品永久| a视频在线观看| 欧美做受高潮电影o| 自拍偷拍亚洲综合| 精品国产亚洲一区二区在线观看| 亚洲最新av网址| 国产精品一区二区在线播放| 别急慢慢来1978如如2| 国产精品欧美日韩一区二区| 国产精品狼人久久影院观看方式| 超碰97久久国产精品牛牛| 国产欧美精品一区二区三区| 精品国产伦理网| 日产国产欧美视频一区精品| 狠狠操第一页| 快播日韩欧美| 国产视频精品一区二区三区| 欧美96一区二区免费视频| 佐山爱痴汉视频一区二区三区 | 精品免费国产二区三区| 正在播放日韩欧美一页| 天天干天天操天天玩| 亚洲精品视频免费| 全部av―极品视觉盛宴亚洲| 亚洲男男av| 国产黄色小视频在线| 亚洲综合首页| 国产精品亚洲自拍| 色88888久久久久久影院按摩 | 伊人激情综合网| 18成人在线观看| 91九色精品| 僵尸再翻生在线观看| 国产精品一区二区三区四区色| 日韩国产欧美精品| 亚洲国产第一页| 国产精品二三区| 你懂的一区二区三区| av在线最新| 在线播放你懂的| 国产黄页在线观看| 久久艹中文字幕| 91av视频在线免费观看| 亚洲国模精品一区| 亚洲成a人片在线观看中文| 日韩不卡在线视频| 日本电影免费看| 裸模一区二区三区免费| 五月婷婷综合激情| 国产精品乱子久久久久| 国产一区欧美二区| 国产剧情一区二区| 免费av成人在线| 亚洲第一毛片| 香蕉视频一区| 国产91在线精品| 精品网站999| 日韩伦理在线一区| 尤物视频免费在线观看| 亚洲欧美日韩国产成人综合一二三区| 欧美xxxx做受欧美| 国产一区二区三区高清在线观看| 国产乱码精品一区二区三| 久久99性xxx老妇胖精品| 成人知道污网站| 一区中文字幕电影| 国产一区二区三区日韩精品| 日本精品在线播放| 国产美女一区视频| 亚洲网站情趣视频| 九九久久九九久久| 成人字幕网zmw| 99久久国产免费免费| 日韩在线观看成人| 精品日韩99亚洲| 亚洲成人自拍一区| 91精品国产综合久久久久久久| 亚洲超碰精品一区二区| 欧美日韩在线直播| 日韩欧美在线视频| 国产女人18毛片水真多成人如厕 | 久久五月天婷婷| 欧美剧在线观看| 日韩在线视频观看正片免费网站| 欧美日韩一级黄| 久久亚洲一区二区三区明星换脸| 欧美福利视频| 成人综合婷婷国产精品久久蜜臀| 欧美日韩三级| 国产成人三级| 国产精品视屏| 欧美91在线| 国产麻豆一区二区三区| 国产精选在线| 久久久久久久久久久久电影| 欧美a级大片在线| 黄色在线观看www| 亚洲调教一区| 欧美aaaaaaaaaaaa| 亚洲激精日韩激精欧美精品| 老司机久久99久久精品播放免费| 欧美日韩亚洲一区| 欧美一区免费| 久久久蜜桃一区二区人| 久久久不卡网国产精品一区| 欧美日韩国产天堂| 亚洲一区999| 国产成人精品免费视频| 国产精品yjizz|