我的編碼習慣 —— Controller規範

Java團長_發表於2018-10-15

前文回顧:


1. 《吐槽我見過的最爛的Java程式碼》

2. 《我的編碼習慣 —— 介面定義》


第一篇文章中,我貼了2段程式碼,第1段是原生態的,第2段是我指定了介面定義規範,使用AOP技術之後最終交付的程式碼,從15行到1行,自己感受一下。


今天來說說大家關注的AOP如何實現。

先說說Controller規範,主要的內容是就是介面定義裡面的內容,你只要遵循裡面的規範,controller就問題不大,除了這些,還有另外的幾點:

1. 所有函式返回統一的ResultBean/PageResultBean格式

原因見我的介面定義這個貼。沒有統一格式,AOP無法玩。

2. ResultBean/PageResultBean是controller專用的,不允許往後傳!

3. Controller做引數格式的轉換,不允許把json,map這類物件傳到services去,也不允許services返回json、map。

一般情況下!寫過程式碼都知道,map,json這種格式靈活,但是可讀性差,如果放業務資料,每次閱讀起來都比較困難。定義一個bean看著工作量多了,但程式碼清晰多了。

4. 引數中一般情況不允許出現Request,Response這些物件

主要是可讀性問題,一般情況下。

5. 不需要列印日誌

日誌在AOP裡面會列印,而且我的建議是大部分日誌在Services這層列印。

規範裡面大部分是 不要做的項多,要做的比較少,落地比較容易。

ResultBean定義帶泛型,使用了lombok。

640640


AOP程式碼,主要就是列印日誌和捕獲異常,異常要區分已知異常和未知異常,其中未知的異常是我們重點關注的,可以做一些郵件通知啥的,已知異常可以再細分一下,可以不同的異常返回不同的返回碼:


/**
* 處理和包裝異常
*/

public class ControllerAOP {
 private static final Logger logger = LoggerFactory.getLogger(ControllerAOP.class);

 public Object handlerControllerMethod(ProceedingJoinPoint pjp) {
   long startTime = System.currentTimeMillis();

   ResultBean<?> result;

   try {
     result = (ResultBean<?>) pjp.proceed();
     logger.info(pjp.getSignature() + "use time:" + (System.currentTimeMillis() - startTime));
   } catch (Throwable e) {
     result = handlerException(pjp, e);
   }

   return result;
 }

 private ResultBean<?> handlerException(ProceedingJoinPoint pjp, Throwable e) {
   ResultBean<?> result = new ResultBean();

   // 已知異常
   if (e instanceof CheckException) {
     result.setMsg(e.getLocalizedMessage());
     result.setCode(ResultBean.FAIL);
   } else if (e instanceof UnloginException) {
     result.setMsg("Unlogin");
     result.setCode(ResultBean.NO_LOGIN);
   } else {
     logger.error(pjp.getSignature() + " error ", e);
     //TODO 未知的異常,應該格外注意,可以傳送郵件通知等
     result.setMsg(e.toString());
     result.setCode(ResultBean.FAIL);
   }

   return result;
 }
}


AOP配置:(關於用java程式碼還是xml配置,這裡我傾向於xml配置,因為這個會不定期改動)


<!-- aop -->
 <aop:aspectj-autoproxy />
 <beans:bean id="controllerAop" class="xxx.common.aop.ControllerAOP" />
 <aop:config>
   <aop:aspect id="myAop" ref="controllerAop">
     <aop:pointcut id="target"
       expression="execution(public xxx.common.beans.ResultBean *(..))" />

     <aop:around method="handlerControllerMethod" pointcut-ref="target" />
   </aop:aspect>
 </aop:config>


現在知道為什麼要返回統一的一個ResultBean了:


  • 為了統一格式

  • 為了應用AOP

  • 為了包裝異常資訊

分頁的PageResultBean大同小異,大家自己依葫蘆畫瓢自己完成就好了。

貼一個簡單的controller(左邊的箭頭表示AOP攔截了)。請對比吐槽我見過的最爛的Java程式碼裡面原來的程式碼檢視,沒有對比就沒有傷害。

640


最後說一句,先有統一的介面定義規範,然後有AOP實現。先有思想再有技術。技術不是關鍵,AOP技術也很簡單,這個帖子的關鍵點不是技術,而是習慣和思想,不要撿了芝麻丟了西瓜。網路上講技術的貼多,講習慣、風格的少,這些都是我工作多年的行之有效的經驗之談,望有緣人珍惜。


覺得有用請點贊加轉發!


(完)


640

Java團長

專注於Java乾貨分享

640

掃描上方二維碼獲取更多Java乾貨

相關文章