Spring統一日誌處理(AOP)
阿新 • • 發佈:2018-11-02
來現在公司的緣故,公司大佬使用的AOP比較多,本來在校時候對AOP只是一知半解,在現在公司呆了半年,用到了各種攔截器,對AOP有了許多新的認識。此處用統一日誌處理就是使用的是Spring AOP實現的。
定義統一日誌表,用在將所有請求都記錄在表中,方便以後查閱。
CREATE TABLE `t_union_log` ( `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵', `dev_mac` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '裝置MAC', `user_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '使用者身份', `level` int(11) NULL DEFAULT 0 COMMENT '日誌級別,0-最高級別', `method` varchar(25) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作方式', `remote_host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作IP地址', `request_uri` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '請求URI', `user_agent` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '使用者代理', `module_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '模組名稱', `param` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '請求引數', `result` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '結果', `spent` bigint(20) NULL DEFAULT NULL COMMENT '耗費時間-毫秒', `ctime` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間', PRIMARY KEY (`id`) USING BTREE )
定義實體類與DAO,此處使用的是mybatis-plus,使用其他的也可以,自行選擇,這些都不重要,重要的是後面的aop攔截器。
@TableName("t_union_log") public class UnionLogEntity { @TableId(value = "id",type = IdType.AUTO) private Long id; private String devMac; private String userId; private Integer level; private String method; private String remoteHost; private String requestUri; private String userAgent; private String moduleName; private String param; private String result; private Long spent; private Date ctime; Getter... Setter... }
@Mapper
public interface UnionLogMapper extends BaseMapper<UnionLogEntity>{
}
實現統一日誌的攔截。原理很簡單,只要懂得一些AOP方面的知識,看程式碼很容易看的懂。特別注意的是,在不需要攔截的URI,一定不能進行日誌列印(如:檔案下載介面,會報記憶體溢位錯誤,以前寫檔案下載的時候遇到,再次銘記)
/**統一日誌處理*/ @Aspect @Component public class GlobalLogAspect { private Logger logger = LoggerFactory.getLogger(GlobalLogAspect.class); private static final String POINTCUT = "execution(* com.xichuan.wechat.*.controller.*.*(..)) "; private static final ThreadLocal<Map<Object,Object>> paramLocal = new ThreadLocal<>(); private static final ThreadLocal<Map<Object,Object>> resultsLocal = new ThreadLocal<>(); private static final ThreadLocal<Long> start = new ThreadLocal<>(); private static final ThreadLocal<Long> end = new ThreadLocal<>(); private static final ThreadLocal<HttpServletRequest> httpRequest = new ThreadLocal<>(); @Autowired UnionLogMapper unionLogMapper; @Before(POINTCUT) public void beforeAspectHandler(){ start.set(System.currentTimeMillis()); } @After(POINTCUT) public void afterAspectHandler(){ HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); String uri = request.getRequestURI(); if(uri.equals("")){ /**不進行日誌攔截的URI*/ logger.info("global log Aspect untreated uri:"+uri); }else{ end.set(System.currentTimeMillis()); this.tracer(); } } @Around(POINTCUT) public Object aroundAspectHandler(ProceedingJoinPoint joinPoint)throws Throwable{ Object[] param = joinPoint.getArgs(); Map<Object,Object> argMap = new LinkedHashMap<>(); argMap.put("params",param); paramLocal.set(argMap); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); httpRequest.set(request); Object result = joinPoint.proceed(); Map<Object,Object> resMap = new LinkedHashMap<>(); resMap.put("results",result); resultsLocal.set(resMap); return result; } public void tracer(){ try { HttpServletRequest request = httpRequest.get(); Gson gson = new Gson(); logger.info("Request PATH: {}, Time: {}, Consumed: {}ms, Param: {}, Result: {}\n", "["+request.getRequestURI()+"]", new SimpleDateFormat("yyyy-MM-dd HH:mm:s").format(start.get()), (end.get()-start.get()), gson.toJson(paramLocal.get()), gson.toJson(resultsLocal.get())); UnionLogEntity unionLog = new UnionLogEntity(); unionLog.setCtime(new Date()); unionLog.setMethod(request.getMethod()); unionLog.setRequestUri(request.getRequestURI()); unionLog.setRemoteHost(request.getRemoteHost()); unionLog.setUserAgent(request.getHeader("User-Agent")); unionLog.setParam(gson.toJson(paramLocal.get())); unionLog.setResult(gson.toJson(resultsLocal.get())); unionLog.setSpent(end.get()-start.get()); unionLog.setUserId(request.getHeader(("account_id"))); unionLog.setDevMac(request.getHeader(("dev_mac"))); unionLog.setModuleName("cmd"); unionLogMapper.insert(unionLog); }finally { httpRequest.remove(); paramLocal.remove(); resultsLocal.remove(); start.remove(); end.remove(); } } }