一:首先定义日志切面注解
/**
*
* * 自定义操作日志注解
* @author zhoupengwei
*/
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface OperLog {
String operModul() default ""; // 操作模块
String operType() default ""; // 操作类型
String operDesc() default ""; // 操作说明
}
二:日志切面处理类
/**
* * 自定义操作日志注解
*
* @author zhoupengwei
*/
@Aspect
@Component
public class OperLogAspect {
@Resource
OperLogDAO operLogDAO;
@Resource
TokenUtils tokenUtils;
/**
* 设置操作日志切入点 记录操作日志 在注解的位置切入代码
*/
@Pointcut("@annotation(com.cfht.demo.aop.OperLog)")
public void operLogPoinCut() {
}
/**
* 设置操作异常切入点记录异常日志 扫描所有controller包下操作
*/
@Pointcut("execution(* com.cfht.demo.controller..*.*(..))")
public void operExceptionLogPoinCut() {
}
@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);
OperLogEntity operlog = new OperLogEntity();
try {
// operlog.setOperId(UuidUtil.get32UUID()); // 主键ID
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取操作
OperLog opLog = method.getAnnotation(OperLog.class);
if (opLog != null) {
operlog.setOperModel(opLog.operModul()); // 操作模块
operlog.setOperType(opLog.operType()); // 操作类型
operlog.setOperDesc(opLog.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 = JSON.toJSONString(rtnMap);
if (!"".equals(request.getHeader("token")) && null != request.getHeader("token")) {
Claims claims1 = tokenUtils.getTokenUser(request.getHeader("token"));
if (null != claims1) {
operlog.setOperUserId(claims1.getId()); // 请求用户ID
operlog.setOperUserName(claims1.get("sub").toString()); // 请求用户名称
operlog.setOperIp(getIpAddress(request)); // 请求IP
}
}
operlog.setOperRequParam(params); // 请求参数
operlog.setOperRespParam(JSON.toJSONString(keys)); // 返回结果
operlog.setOperUrl(request.getRequestURI()); // 请求URI
operlog.setDataType("1"); //1 正常日常 0:异常日志
operLogDAO.insert(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;
}
/***
* 获取客户端IP地址
*
*/
private String getIpAddress(HttpServletRequest request) {
String ipAddress = null;
try {
ipAddress = request.getHeader("x-forwarded-for");
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
ipAddress = request.getRemoteAddr();
if (ipAddress.equals("127.0.0.1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress = inet.getHostAddress();
}
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.length() > 15) { // "***.***.***.***".length()
// = 15
if (ipAddress.indexOf(",") > 0) {
ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
}
}
} catch (Exception e) {
ipAddress = "";
}
// ipAddress = this.getRequest().getRemoteAddr();
return ipAddress;
}
}
三:创建日志实体类、数据库新建log表
/**
* <p>Description: [入参]</p>
* Created on 2021-04-25 09:58:23
*
* @author zhoupengwei
*/
@Data
@ApiModel("入参")
public class OperLogVo{
/**
* 数据类型
*/
@ApiModelProperty(value = "数据类型",name = "dataType")
private String dataType;
/**
* 异常信息
*/
@ApiModelProperty(value = "异常信息",name = "excMessage")
private String excMessage;
/**
* 异常名称
*/
@ApiModelProperty(value = "异常名称",name = "excName")
private String excName;
/**
* 日志id
*/
@ApiModelProperty(value = "日志id",name = "id")
private Long id;
/**
* 操作描述
*/
@ApiModelProperty(value = "操作描述",name = "operDesc")
private String operDesc;
/**
* 操作ip
*/
@ApiModelProperty(value = "操作ip",name = "operIp")
private String operIp;
/**
* 操作方法
*/
@ApiModelProperty(value = "操作方法",name = "operMethod")
private String operMethod;
/**
* 功能模块
*/
@ApiModelProperty(value = "功能模块",name = "operModel")
private String operModel;
/**
* 请求参数
*/
@ApiModelProperty(value = "请求参数",name = "operRequParam")
private String operRequParam;
/**
* 返回参数
*/
@ApiModelProperty(value = "返回参数",name = "operRespParam")
private String operRespParam;
/**
* 操作类型
*/
@ApiModelProperty(value = "操作类型",name = "operType")
private String operType;
/**
* 操作地址
*/
@ApiModelProperty(value = "操作地址",name = "operUrl")
private String operUrl;
/**
* 人员id
*/
@ApiModelProperty(value = "人员id",name = "operUserId")
private String operUserId;
/**
* 人员name
*/
@ApiModelProperty(value = "人员name",name = "operUserName")
private String operUserName;
}
四:在控制层添加日志注解
@UserLoginToken
@GetMapping("/getMessage")
@OperLog(operModul = "用户管理", operType = "TEST", operDesc = "测试接口")
public String getMessage(StringBuffer token) {
return "你已通过验证";
}