實現一,使用log日誌,無差別記錄
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.UUID;
/**
* 記錄http請求日誌。作用aop,對所有的Controller的所有訪求進行攔截。獲取其中參數,進行記錄
*/
@Aspect
@Component
public class WebLogAspect {
private Logger logger = LoggerFactory.getLogger("httpReqLog");
//用於計算 該交請求執行的時間
ThreadLocal<Long> startTime = new ThreadLocal<>();
//區分一次請求的tonken
ThreadLocal<String> tonken = new ThreadLocal<>();
/**
* 切點,com.tod.ctm.controller包下的所有類的所有方法
*/
@Pointcut("execution(* com.tod.sgop.controller..*.*(..))")
public void webLog(){}
/**
* controller執行前進行日誌記錄,記錄url和參數
*/
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
String uuid = UUID.randomUUID().toString();
startTime.set(System.currentTimeMillis());
tonken.set(uuid);
// 接收到請求,記錄請求內容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 記錄下請求內容
logger.info("["+uuid+"] URL : " + request.getRequestURL().toString());
//logger.info("HTTP_METHOD : " + request.getMethod());
//logger.info("IP : " + request.getRemoteAddr());
//logger.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
logger.info("["+uuid+"] ARGS : " + Arrays.toString(joinPoint.getArgs()));
}
/**
* controller執行後進行日誌記錄,記錄返回參數和執行時間
*/
@AfterReturning(returning = "ret", pointcut = "webLog()")
public void doAfterReturning(Object ret) throws Throwable {
// 處理完請求,返回內容
logger.info("["+tonken.get()+"] RESPONSE : " + ret);
logger.info("["+tonken.get()+"] SPEND TIME : " + (System.currentTimeMillis() - startTime.get()));
}
}
實現二、存入數據庫,根據請求接口類別來記錄(只記錄接口有OperLog 註解的請求)
import com.tod.bim.annotation.OperLog;
import com.tod.bim.domain.OperationLog;
import com.tod.bim.domain.User;
import com.tod.bim.service.OperationLogService;
import com.tod.bim.service.UserService;
import com.tod.bim.utils.SessionUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author zj
* @version 1.0
* @functin
* @date 2020/5/19 10:39
*/
@Aspect
@Component
public class OperLogAspect {
@Autowired
private UserService userService;
@Autowired
private OperationLogService operationLogService;
/**
* 設置操作日誌切入點 記錄操作日誌 在註解的位置切入代碼
*/
@Pointcut("@annotation(com.tod.bim.annotation.OperLog)")
public void operLogPoinCut() {
}
/**
* 正常返回通知,攔截用戶操作日誌,連接點正常執行完成後執行, 如果連接點拋出異常,則不會執行
*
* @param joinPoint 切入點
* @param keys 返回結果
*/
@AfterReturning(value = "operLogPoinCut()", returning = "keys")
public void saveOperLog(JoinPoint joinPoint, Object keys) {
// 獲取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 從獲取RequestAttributes中獲取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
OperationLog operlog = new OperationLog();
try {
// 從切面織入點處通過反射機制獲取織入點處的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 獲取切入點所在的方法
Method method = signature.getMethod();
// 獲取操作
OperLog opLog = method.getAnnotation(OperLog.class);
if (opLog != null) {
String operType = opLog.operType().getValue();
String operDesc = opLog.operDesc();
operlog.setOperType(operType); // 操作類型
operlog.setOperDesc(operDesc); // 操作描述
}
// 獲取請求的類名
String className = joinPoint.getTarget().getClass().getName();
// 獲取請求的方法名
String methodName = method.getName();
methodName = className + "." + methodName;
operlog.setOperMethod(methodName); // 請求方法
// 請求的參數
Map<String, String> rtnMap = converMap(request.getParameterMap());
// 將參數所在的數組轉換成json
String params = new JSONObject(rtnMap).toString();
operlog.setOperRequParam(params); // 請求參數
operlog.setOperRespParam(""); // 返回結果
User loginUser = SessionUtil.getUserSession();
operlog.setOperCname(loginUser.getCname());
operlog.setOperUserName(loginUser.getUsername());
operlog.setOperRoles(loginUser.getRoleNames());
operlog.setOperPhone(loginUser.getPhone());
operlog.setOperIp(request.getRemoteAddr()); // 請求IP
operlog.setOperUri(request.getRequestURI()); // 請求URI
operlog.setOperTime(new Date());
operationLogService.save(operlog);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 轉換request 請求參數
*
* @param paramMap request獲取的參數數組
*/
public Map<String, String> converMap(Map<String, String[]> paramMap) {
Map<String, String> rtnMap = new HashMap<String, String>();
for (String key : paramMap.keySet()) {
rtnMap.put(key, paramMap.get(key)[0]);
}
return rtnMap;
}
/**
* 轉換異常信息爲字符串
*
* @param exceptionName 異常名稱
* @param exceptionMessage 異常信息
* @param elements 堆棧信息
*/
public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) {
StringBuffer strbuff = new StringBuffer();
for (StackTraceElement stet : elements) {
strbuff.append(stet + "\n");
}
String message = exceptionName + ":" + exceptionMessage + "\n\t" + strbuff.toString();
return message;
}
}
import com.tod.bim.enu.OperType;
import java.lang.annotation.*;
/**
* @author zj
* @version 1.0
* @functin 自定義操作日誌註解
* @date 2020/5/19 10:36
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {
OperType operType() ; // 操作類型
String operDesc() default ""; // 操作說明
}
/**
* @author zj
* @version 1.0
* @functin
* @date 2020/5/19 11:39
*/
public enum OperType {
modify("修改"),
query("查詢"),
delete("刪除");
private String value;
OperType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
@RequestMapping("/monitoring")
@ResponseBody
@OperLog(operType = OperType.query, operDesc = "查詢系統監測信息")
public AjaxResult monitoring(
@RequestParam(defaultValue = "10") int pageSize,
@RequestParam(defaultValue = "0") int pageNo) {
List<SystemMonitoring> monitoring = systemMonitoringService.monitoring();
return AjaxResult.ajaxSuccessResult("成功", monitoring);
}