使用AOP處理異常與日誌列印
阿新 • • 發佈:2019-01-10
本文轉載自曉風輕部落格:https://xwjie.github.io/
ResultBean定義
定義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實現
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>
簡單示例
貼一個簡單的controller。請對比 程式設計師你為什麼這麼累?裡面原來的程式碼檢視,沒有對比就沒有傷害。
/**
* 配置物件處理器
*
* @author 曉風輕 https://github.com/xwjie/PLMCodeTemplate
*/
@RequestMapping("/config")
@RestController
public class ConfigController {
private final ConfigService configService;
public ConfigController(ConfigService configService) {
this.configService = configService;
}
@GetMapping("/all")
public ResultBean<Collection<Config>> getAll() {
return new ResultBean<Collection<Config>>(configService.getAll());
}
/**
* 新增資料, 返回新物件的id
*
* @param config
* @return
*/
@PostMapping("/add")
public ResultBean<Long> add(Config config) {
return new ResultBean<Long>(configService.add(config));
}
/**
* 根據id刪除物件
*
* @param id
* @return
*/
@PostMapping("/delete")
public ResultBean<Boolean> delete(long id) {
return new ResultBean<Boolean>(configService.delete(id));
}
@PostMapping("/update")
public ResultBean<Boolean> update(Config config) {
configService.update(config);
return new ResultBean<Boolean>(true);
}
}