我的編碼習慣 - Controller規範

先說說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。

preview

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 {
      logger.error(pjp.getSignature() + " error ", e);

      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了:

  1. 爲了統一格式
  2. 爲了應用AOP
  3. 爲了包裝異常信息


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

貼一個簡單的controller(左邊的箭頭表示AOP攔截了)。請對比程序員你爲什麼這麼累?裏面原來的代碼查看,沒有對比就沒有傷害。

@RequestMapping("/config")
@RequestController
public class ConfigController{
	@AutoWired
	ConfigService configService
	
	@GetMapping("/all")
	public ResultBean<Collection<Config>> getAll(){
		return new ResultBean<Collection<Config>>(configService.getAll());
	}
	
	@PostMapping("/add")
	public ResultBean<Long> add(Config config){
		return new ResultBean<Long>(configService.add(config));
	}
	
	@PostMapping("/delete")
	public ResultBean<Boolean> delete(long id){
		return new ResultBean<Boolean>(configService.delete(id))
	}
}


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


本文作者:曉風輕
原文鏈接:https://zhuanlan.zhihu.com/p/28717374
版權歸作者所有,轉載請註明出處


發佈了8 篇原創文章 · 獲贊 17 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章