Spring Boot 2.x(六):優雅的統一返回值

目錄

  • 為什么要統一返回值
  • ReturnVO
  • ReturnCode
  • 使用ReturnVO
  • 使用AOP進行全局異常的處理
  • 云擼貓
  • 公眾號

為什么要統一返回值

在我們做后端應用的時候,前后端分離的情況下,我們經常會定義一個數據格式,通常會包含codemessagedata這三個必不可少的信息來方便我們的交流,下面我們直接來看代碼

ReturnVO

package indi.viyoung.viboot.util;import java.util.Properties;/*** 統一定義返回類** @author yangwei* @since 2018/12/20*/
public class ReturnVO {private static final Properties properties = ReadPropertiesUtil.getProperties(System.getProperty("user.dir") + "/viboot-common/src/main/resources/response.properties");/*** 返回代碼*/private String code;/*** 返回信息*/private String message;/*** 返回數據*/private Object data;public Object getData() {return data;}public void setData(Object data) {this.data = data;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}/*** 默認構造,返回操作正確的返回代碼和信息*/public ReturnVO() {this.setCode(properties.getProperty(ReturnCode.SUCCESS.val()));this.setMessage(properties.getProperty(ReturnCode.SUCCESS.msg()));}/*** 構造一個返回特定代碼的ReturnVO對象* @param code*/public ReturnVO(ReturnCode code) {this.setCode(properties.getProperty(code.val()));this.setMessage(properties.getProperty(code.msg()));}/*** 默認值返回,默認返回正確的code和message* @param data*/public ReturnVO(Object data) {this.setCode(properties.getProperty(ReturnCode.SUCCESS.val()));this.setMessage(properties.getProperty(ReturnCode.SUCCESS.msg()));this.setData(data);}/*** 構造返回代碼,以及自定義的錯誤信息* @param code* @param message*/public ReturnVO(ReturnCode code, String message) {this.setCode(properties.getProperty(code.val()));this.setMessage(message);}/*** 構造自定義的code,message,以及data* @param code* @param message* @param data*/public ReturnVO(ReturnCode code, String message, Object data) {this.setCode(code.val());this.setMessage(message);this.setData(data);}@Overridepublic String toString() {return "ReturnVO{" +"code='" + code + '\'' +", message='" + message + '\'' +", data=" + data +'}';}
}

在這里,我提供了幾個構造方法以供不同情況下使用。代碼的注釋已經寫得很清楚了,大家也可以應該看的比較清楚~

ReturnCode

細心的同學可能發現了,我單獨定義了一個ReturnCode枚舉類用于存儲代碼和返回的Message:

package indi.viyoung.viboot.util;/*** @author yangwei* @since 2018/12/20*/
public enum ReturnCode {/** 操作成功 */SUCCESS("SUCCESS_CODE", "SUCCESS_MSG"),/** 操作失敗 */FAIL("FAIL_CODE", "FAIL_MSG"),/** 空指針異常 */NullpointerException("NPE_CODE", "NPE_MSG"),/** 自定義異常之返回值為空 */NullResponseException("NRE_CODE", "NRE_MSG");private ReturnCode(String value, String msg){this.val = value;this.msg = msg;}public String val() {return val;}public String msg() {return msg;}private String val;private String msg;
}

這里,我并沒有將需要存儲的數據直接放到枚舉中,而是放到了一個配置文件中,這樣既可以方便我們進行相關信息的修改,并且閱讀起來也是比較方便。

SUCCESS_CODE=2000
SUCCESS_MSG=操作成功FAIL_CODE=5000
FAIL_MSG=操作失敗NPE_CODE=5001
NPE_MSG=空指針異常NRE_CODE=5002
NRE_MSG=返回值為空

注意,這里的屬性名和屬性值分別與枚舉類中的value和msg相對應,這樣,我們才可以方便的去通過I/O流去讀取。

這里需要注意一點,如果你使用的是IDEA編輯器,需要修改以下的配置,這樣你編輯配置文件的時候寫的是中文,實際上保存的是ASCII字節碼。
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZpX3lvdW5nXzk1,size_16,color_FFFFFF,t_70

下面,來看一下讀取的工具類:

package indi.viyoung.viboot.util;import java.io.*;
import java.util.Iterator;
import java.util.Properties;/*** 讀取*.properties中的屬性* @author vi* @since 2018/12/24 7:33 PM*/
public class ReadPropertiesUtil {public static Properties getProperties(String propertiesPath){Properties properties = new Properties();try {InputStream inputStream = new BufferedInputStream(new FileInputStream(propertiesPath));properties.load(inputStream);} catch (IOException e) {e.printStackTrace();}return properties;}
}

這里我直接寫了一個靜態的方法,傳入的參數是properties文件的位置,這樣的話,本文最初代碼中的也就得到了解釋。

    private static final Properties properties = ReadPropertiesUtil.getProperties(System.getProperty("user.dir") + "/viboot-common/src/main/resources/response.properties");

使用ReturnVO

    @RequestMapping("/test")public ReturnVO test(){try {//省略//省略}  catch (Exception e) {e.printStackTrace();}return new ReturnVO();}

下面我們可以去訪問這個接口,看看會得到什么:
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZpX3lvdW5nXzk1,size_16,color_FFFFFF,t_70
但是,現在問題又來了,因為try...catch...的存在,總是會讓代碼變得重復度很高,一個接口你都至少要去花三到十秒去寫這個接口,如果不知道編輯器的快捷鍵,更是一種噩夢。我們只想全心全意的去關注實現業務,而不是花費大量的時間在編寫一些重復的"剛需"代碼上。

使用AOP進行全局異常的處理

(這里,我只是對全局異常處理進行一個簡單的講解,后面也就是下一節中會詳細的講述)

/*** 統一封裝返回值和異常處理** @author vi* @since 2018/12/20 6:09 AM*/
@Slf4j
@Aspect
@Order(5)
@Component
public class ResponseAop {private static final Properties properties = ReadPropertiesUtil.getProperties(System.getProperty("user.dir") + "/viboot-common/src/main/resources/response.properties");/*** 切點*/@Pointcut("execution(public * indi.viyoung.viboot.*.controller..*(..))")public void httpResponse() {}/*** 環切*/@Around("httpResponse()")public ReturnVO handlerController(ProceedingJoinPoint proceedingJoinPoint) {ReturnVO returnVO = new ReturnVO();try {//獲取方法的執行結果Object proceed = proceedingJoinPoint.proceed();//如果方法的執行結果是ReturnVO,則將該對象直接返回if (proceed instanceof ReturnVO) {returnVO = (ReturnVO) proceed;} else {//否則,就要封裝到ReturnVO的data中returnVO.setData(proceed);}}  catch (Throwable throwable) {//如果出現了異常,調用異常處理方法將錯誤信息封裝到ReturnVO中并返回returnVO = handlerException(throwable);}return returnVO;}/*** 異常處理*/ private ReturnVO handlerException(Throwable throwable) {ReturnVO returnVO = new ReturnVO();//這里需要注意,返回枚舉類中的枚舉在寫的時候應該和異常的名稱相對應,以便動態的獲取異常代碼和異常信息//獲取異常名稱的方法String errorName = throwable.toString();errorName = errorName.substring(errorName.lastIndexOf(".") + 1);//直接獲取properties文件中的內容returnVO.setMessage(properties.getProperty(ReturnCode.valueOf(errorName).msg()));returnVO.setCode(properties.getProperty(ReturnCode.valueOf(errorName).val()));return returnVO;}
}

如果,我們需要在每一個項目中都可以這么去做,需要將這個類放到一個公用的模塊中,然后在pom中導入這個模塊

        <dependency><groupId>indi.viyoung.course</groupId><artifactId>viboot-common</artifactId><version>1.0-SNAPSHOT</version></dependency>

這里需要注意一點,必須保證你的切點的正確書寫!!否則就會導致切點無效,同時需要在啟動類中配置:

@ComponentScan(value = "indi.viyoung.viboot.*")

導入的正是common包下的所有文件,以保證可以將ResponseAop這個類加載到Spring的容器中。

下面我們來測試一下,訪問我們經過修改后的編寫的findAll接口:

    @RequestMapping("/findAll")public Object findAll(){return userService.list();}

PS:這里我將返回值統一為Object,以便數據存入data,實際類型應是Service接口的返回類型。如果沒有返回值的話,那就可以new一個ReturnVO對象直接通過構造方法賦值即可。關于返回類型為ReturnVO的判斷,代碼中也已經做了特殊的處理,并非存入data,而是直接返回。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZpX3lvdW5nXzk1,size_16,color_FFFFFF,t_70
下面,我們修改一下test方法,讓他拋出一個我們自定義的查詢返回值為空的異常:

    @RequestMapping("/test")public ReturnVO test(){throw new NullResponseException();}

下面,我們再來訪問以下test接口:
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZpX3lvdW5nXzk1,size_16,color_FFFFFF,t_70
可以看到,正如我們properties中定義的那樣,我們得到了我們想要的消息。

原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。

源碼可以去github或者碼云上進行下載,后續的例子都會同步更新。

云擼貓

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3ZpX3lvdW5nXzk1,size_16,color_FFFFFF,t_70

公眾號

20181228073632641.jpg

如果幫到了你,請點擊推薦讓更多人看到~

轉載于:https://www.cnblogs.com/viyoung/p/10188456.html

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

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

相關文章

Object defineProperty

Object defineProperty一、簡介1. 屬性表2.互斥性3. get、set的簡單使用二、深入1.定義常量2. Object.preventExtensions() 禁止對象拓展(不可逆)3. Object.seal() 密封(不可逆)4. Object.freeze() 凍結(不可逆)三、應用一、簡介 defineProperty可以詳細的配置一個對象的屬性的…

jhope代碼分析以及網站結構

如下圖所示&#xff0c;為Extjs部分代碼提供的網頁結構&#xff1a;網站看上去本來是這樣的前端采用ExtJS&#xff0c;與后臺的SpringMVCSpringHibernate進行數據交互。之前分析過登錄的過程&#xff0c;不贅述在loginController處理登錄返回結果的最后&#xff0c;如下語句也就…

Ubuntu下Authentication token manipulation error或者Authentication Failure解決辦法

在Ubuntu18.04使用以下命令出現以下錯誤: 用passwd為新建用戶或者root添加密碼:Authentication token manipulation error 切換root用戶出現Authentication Failure. 網上出現了大致兩種方法: 第一種&#xff1a;用戶文件和密碼文件被保護&#xff0c;用chattr命令移除保護即可…

初學者:如何使用虛擬PC將Windows 7安裝到虛擬機

Continuing in our series covering how to use Virtual PC, this week we’ll be showing you how to install Windows 7 into a virtual machine. It’s a very simple process, but here’s the step-by-step guide for beginners. 繼續我們的系列文章&#xff0c;介紹如何使…

arcgis本地服務快速遷移到新機

情景 在本機或服務器發布了幾十、幾百個gis服務&#xff0c;當換電腦或者換服務器時不可能挨個找源文件重新發布服務&#xff0c;于是就想著既然是本地文件&#xff0c;一定可以拷貝過去的&#xff0c;經過一番搜索&#xff0c;結果如下: 方案一、遷移至新站點 新機站點創建…

js中 給json對象添加屬性和json數組添加元素

json對象&#xff1a; 比如現在有一個json對象為jsonObj&#xff0c;需要給這個對象添加新的屬性newParam&#xff0c;同時給newParam賦值為pre。做法如下&#xff1a; var jsonObj{param1:22,param2 :33}; 現在給jsonObj添加一個新的屬性newParam jsonObj.newParam pre; 新的…

zabbix中php信息缺失之后的安裝

安裝php下enable bcmath和gettext &#xff08;在安裝php時可以添加 --enable-bcmath --enable-gettext&#xff09;1,bcmath安裝方法bcmath這個擴展在php源安裝包壓縮包中都是有的&#xff0c;需要重新編譯一下才能夠支持&#xff1b;cd php-5.2.7/ext/bcmath&#xff08;源…

極客大佬用什么電腦_極客特惠:筆記本電腦,高清電視和免費應用

極客大佬用什么電腦If you love new gear but not high prices then we’ve got some deals for you; grab some deeply discounted laptops, monitors and HDTVs, and free mobile apps in this week’s Geek Deals roundup. 如果您喜歡新設備&#xff0c;但不喜歡高價&#x…

Linux內核 TCP/IP、Socket參數調優

詳見http://blog.csdn.net/u010009038/article/details/51917460轉載于:https://blog.51cto.com/jack88/2063979

ppt插入html(用office而不是wps)

最近新get到的技能&#xff0c;在ppt里面插入html&#xff01;注意要用 Microsoft Office PowerPoint 才行&#xff0c;而不是wps&#xff0c;一定要先安裝Microsoft Office PowerPoint再執行以下操作。 1、修改注冊表的值&#xff0c;才能在PowerPoint中插入 Microsoft Web B…

如何使用SkyDrive的25 GB作為映射驅動器以方便訪問

SkyDrive is an online storage system included in Windows Live, which gives you 25 GB of space that you can sync to your desktop. Here’s how to connect it to your Windows 7 computer as a mapped drive. SkyDrive是Windows Live中包含的一個在線存儲系統&#xff…

SpringBoot+Mybatis 框架之 @SelectProvider注解方式搭建

之前搭建了Select標簽來做SringBootMybatis的集成。這次使用SelectProvider標簽的方式搭建一次。 一、搭建SpringBoot的項目 https://start.spring.io/自己配置SpringBoot的項目&#xff0c;點擊“Generate Project”按鈕就可以下載下來一個配置好的SpringBoot項目。 二、項目結…

程鑫峰:1.23日央行推行負利率政策,倫敦金后市行情解析

程鑫峰&#xff1a;1.23日央行推行負利率政策&#xff0c;倫敦金后市行情解析 QQ截圖20180123153028.png ??盡管美國政府關門鬧劇剛剛結束&#xff0c;但交易員、投資者和策略師對于美元的前景依然不太樂觀。美國貨幣政策對美元的影響力減弱可能是全球通貨再膨脹交易的另一個…

從購買域名到nginx,flask搭建自己的網站

搭建一個只屬于自己的網站? 一、注冊域名&#xff08;可選*&#xff09; 1.注冊阿里云賬號 網址&#xff1a;登錄&#xff08;注冊&#xff09; 2.購買域名&#xff1a;阿里云域名注冊 有一元域名、免費域名等。 購買過程中需要創建信息模板&#xff08;必須完成郵箱真實…

alexa語音實現_如何通過語音刪除Alexa錄音

alexa語音實現Amazon亞馬孫Amazon is rolling out new privacy features today for Alexa. In addition to an educational “privacy hub,” the company lets you delete your stored recordings by voice. But it’s off by default; you’ll need to flip a switch. 亞馬遜…

linux如何查看所有的用戶(user)、用戶組(group)、密碼(password/passwd)

linux如何查看所有的用戶和組信息_百度經驗https://jingyan.baidu.com/article/a681b0de159b093b184346a7.html linux添加用戶、用戶組、密碼_百度經驗https://jingyan.baidu.com/article/335530da8b7e0419cb41c3e5.html 給用戶開通sudo權限 xxx is not in the sudoers file.Th…

angular之兩種路由

安裝angular npm install -g angular/cli ng new myapp ng g component componentName 自帶路由 引入&#xff1a;angular-route.js <div ng-controllerctr1><a href#home>首頁</a> <a href#mine>我的</a> <div ng-view></div><d…

用scrapy框架寫爬蟲

爬蟲可以發送給引擎的兩種請求&#xff1a; # 1、url&#xff1a;# &#xff08;爬蟲&#xff09;yield scrapy.Request -> 引擎 -> 調度器&#xff08;發送給調度器入隊&#xff09; -> 引擎&#xff08;調度器出隊請求于引擎&#xff09;# -> 下載器&#xff08;…

audacity_如何在Audacity中快速編輯多個文件

audacityGot a bunch of files that need to be edited the same way? You can automate the process to save time and effort using Audacity’s Chain feature and modify tons of files at the same time. 有一堆需要以相同方式編輯的文件&#xff1f; 您可以使用Audacity…

通過api管理grafana

1. 生成api key 參考&#xff1a; http://docs.grafana.org/http_api/auth/ 2.點擊添加后&#xff0c;生成了個獲取一個deshboards的api樣例 3.放到linux上運行測試&#xff0c;結果成功返回。 4. 有些api并不支持使用api key 來連接&#xff0c;如下圖中的搜索用戶接口&#x…