要說Controller的規(guī)范,主要的內(nèi)容是就是接口定義里面的內(nèi)容,你只要遵循里面的規(guī)范,controller就問題不大敢会,除了這些,還有另外的幾點:
1 所有函數(shù)返回統(tǒng)一的ResultBean/PageResultBean格式这嚣,原因見接口定義這個貼鸥昏。沒有統(tǒng)一格式,AOP無法玩姐帚。
2 ResultBean/PageResultBean是controller專用的吏垮,不允許往后傳!
3 Controller做參數(shù)格式的轉(zhuǎn)換罐旗,不允許把json膳汪,map這類對象傳到services去,也不允許services返回json尤莺、map旅敷。
寫過代碼都知道,map颤霎,json這種格式靈活,但是可讀性差涂滴,如果放業(yè)務(wù)數(shù)據(jù)友酱,每次閱讀起來都比較困難。定義一個bean看著工作量多了柔纵,但代碼清晰多了缔杉。
4 參數(shù)中一般情況不允許出現(xiàn)Request,Response這些對象搁料。
主要是因為可讀性問題或详。
5 不需要打印日志
日志在AOP里面會打印系羞,而且我的建議是大部分日志在Services這層打印。
規(guī)范里面大部分是不要做的項多霸琴,要做的比較少椒振,落地比較容易。
ResultBean定義帶泛型梧乘,使用了lombok澎迎。
@Data
public class ResultBean<T> implements Serializable {
private static final long serialVersionUID = 1L;
public static final int NO_LOGIN = -1;
public static final int SUCCESS = 0;
public static final int FAIL = 1;
public static final int NO_PERMISSION = 2;
private String msg = "success";
private int code = SUCCESS;
private T data;
public ResultBean() {
super();
}
public ResultBean(T data) {
super();
this.data = data;
}
public ResultBean(Throwable e) {
super();
this.msg = e.toString();
this.code = FAIL;
}
}
AOP代碼,主要就是打印日志和捕獲異常选调,異常要區(qū)分已知異常和未知異常夹供,其中未知的異常是我們重點關(guān)注的,可以做一些郵件通知啥的仁堪,已知異诚ⅲ可以再細分一下,可以不同的異常返回不同的返回碼:
/**
* 處理和包裝異常
*/
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 未知的異常弦聂,應(yīng)該格外注意鸟辅,可以發(fā)送郵件通知等
result.setMsg(e.toString());
result.setCode(ResultBean.FAIL);
}
return result;
}
}
AOP配置:(關(guān)于用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>
現(xiàn)在知道為什么要返回統(tǒng)一的一個ResultBean了:
- 為了統(tǒng)一格式
- 為了應(yīng)用AOP
- 為了包裝異常信息
分頁的PageResultBean大同小異剔桨,大家自己依葫蘆畫瓢自己完成就好了。
貼一個簡單的controller(左邊的箭頭表示AOP攔截了)徙融。請對比 程序員你為什么這么累洒缀?里面原來的代碼查看,沒有對比就沒有傷害欺冀。
最后說一句树绩,先有統(tǒng)一的接口定義規(guī)范,然后有AOP實現(xiàn)隐轩。先有思想再有技術(shù)饺饭。技術(shù)不是關(guān)鍵,AOP技術(shù)也很簡單职车,這個帖子的關(guān)鍵點不是技術(shù)瘫俊,而是習慣和思想,不要撿了芝麻丟了西瓜悴灵。網(wǎng)絡(luò)上講技術(shù)的貼多扛芽,講習慣、風格的少积瞒,這些都是我工作多年的行之有效的經(jīng)驗之談川尖,望有緣人珍惜。
上一篇:《接口規(guī)范》
下一篇:《日志建議》
本文原著作者:曉風輕
原文鏈接:https://zhuanlan.zhihu.com/p/28705206
版權(quán)歸作者所有茫孔,轉(zhuǎn)載請注明出處