renren-fast 專案解讀:系統日誌處理
阿新 • • 發佈:2018-12-24
系統日誌處理
- 系統日誌,在系統中主要是使用的是註解日誌的形式。通過註解去控制系統日誌列印的內容。
- 基本實現程式碼:這裡通過環繞處理
@Pointcut("@annotation(io.renren.common.annotation.SysLog)") public void logPointCut() { } @Around("logPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { long beginTime = System.currentTimeMillis(); //執行方法 Object result = point.proceed(); //執行時長(毫秒) long time = System.currentTimeMillis() - beginTime; //儲存日誌 saveSysLog(point, time); return result; }
- 主要儲存資訊程式碼:通過切面獲取方法名,方法引數,獲取ip地址,使用者名稱,執行時間等,寫入到庫中。這裡使用的是mybatis,插入資料庫中。在平常我們也可以修改這裡的日誌記錄,放到mongo中或者其他地方。這裡主要還是看實際使用場景選擇技術。
private void saveSysLog(ProceedingJoinPoint joinPoint, long time) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); SysLogEntity sysLog = new SysLogEntity(); SysLog syslog = method.getAnnotation(SysLog.class); if (syslog != null) { //註解上的描 sysLog.setOperation(syslog.value()); } //請求的方法名 String className = joinPoint.getTarget().getClass().getName(); String methodName = signature.getName(); sysLog.setMethod(className + "." + methodName + "()"); //請求的引數 Object[] args = joinPoint.getArgs(); String params = new Gson().toJson(args); sysLog.setParams(params); //獲取request HttpServletRequest request = HttpContextUtils.getHttpServletRequest(); //設定IP地址 sysLog.setIp(IPUtils.getIpAddr(request)); //使用者名稱 String username = ((SysUserEntity) SecurityUtils.getSubject().getPrincipal()).getUsername(); sysLog.setUsername(username); sysLog.setTime(time); try { joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } sysLog.setCreateDate(new Date()); //儲存系統日誌 sysLogService.insert(sysLog); }
- 獲取request物件。HttpContextUtils:這裡使用的Spring的上下文RequestContextHolder來獲取的HttpServletRequest,再通過request獲取相關請求資訊
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
- IPUtils:獲取真實地址ip。 這裡主要是處理代理伺服器的問題,通過代理無法獲取到真實ip。一般代理的真實地址會放到header中,所以這裡的工具類主要是通過獲取header中的引數查詢真實地址。注意這裡,在反向代理中一定要配置,新增真實ip的header
/**
* 獲取IP地址
*
* 使用Nginx等反向代理軟體, 則不能通過request.getRemoteAddr()獲取IP地址
* 如果使用了多級反向代理的話,X-Forwarded-For的值並不止一個,而是一串IP地址,X-Forwarded-For中第一個非unknown的有效IP字串,則為真實IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
return ip;
}