- 导入打印日志,aop,hutool,的依赖,Hutool是一个Java工具包,里面封装了大量的常用工具类,到时候咱们就通过这个工具包中有一个工具类可以用来获取客户端IP地址。 <dependency>
1. <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.6.3</version>
</dependency>
2. 自定义操作类型枚举类 因为基本是增删改查四个方法 /**
* 操作类型枚举类
* @author lichuan
*/
public enum OperationTypeEnum {
/**
* 新增操作
*/
INSERT("新增"),
/**
* 修改操作
*/
UPDATE("修改"),
/**
* 删除操作
*/
DELETE("删除"),
/**
* 查询操作
*/
QUERY("查询"),
/**
* 其它
*/
OTHER("其它");
private String operationType;
OperationTypeEnum(String operationType) {
this.operationType = operationType;
}
public String getOperationType() {
return operationType;
}
}
3. 自定义用来记录用户操作日志的注解 @Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented
public @interface OperationLog {
/**
* 操作模块
* @return
*/
String operationModule() default "";
/**
* 操作类型
* @return
*/
OperationTypeEnum operationType() default OperationTypeEnum.OTHER;
/**
* 操作说明
* @return
*/
String description() default "";
}
4. 写一个方法加上我们自定义的注解
5. 定义用来记录用户操作日志的切面类
import cn.hutool.extra.servlet.ServletUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
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.HashMap;
import java.util.Map;
/**
* @author lichuan
*/
@Aspect
@Component
@Slf4j
public class OperationLogAspect {
/**
* 设置操作日志切入点,在注解的位置切入代码
*/
@Pointcut("execution(public * com.tm.controller..*Controller.*(..))")
public void operationLogPointCut() {
}
/**
* 定义环绕通知
* 1. 环绕通知需要携带ProceedingJoinPoint类型的参数
* 2. 环绕通知类似于动态代理的全过程ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 3. 且环绕通知必须有返回值,返回值即目标方法的返回值
*/
@Around("operationLogPointCut()")
public Object around(ProceedingJoinPoint joinPoint) {
Object result = null;
//获取系统当前时间毫秒值
long beginTime = System.currentTimeMillis();
log.info("环绕通知开始");
try {
//执行目标方法
result = joinPoint.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
//获取系统当前时间毫秒值
long endTime = System.currentTimeMillis();
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 从获取RequestAttributes中获取HttpServletRequest的信息
HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_REQUEST);
//获取ip
String clientIP = ServletUtil.getClientIP(request);
log.info(clientIP);
//获取目标方法执行时间
long usageTime = endTime - beginTime;
// operationLogEntity.setUsageTime(usageTime);
try {
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
//System.out.println(method);
// 获取操作
OperationLog operationLog = method.getAnnotation(OperationLog.class);
if (operationLog != null) {
log.info(operationLog.operationModule());
log.info(operationLog.description());
log.info(operationLog.operationType().getOperationType());
}
// 获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
// 获取请求的方法名
String methodName = method.getName();
methodName = className + "." + methodName;
log.info(methodName);
// 请求方法
// operationLogEntity.setMethodName(methodName);
// 请求的参数
Map<String, String> parameterMap = ServletUtil.getParamMap(request);
// 将参数所在的数组转换成json
String requestParams = new ObjectMapper().writeValueAsString(parameterMap);
// 请求参数
System.out.println(parameterMap);
log.info(requestParams);
// 返回结果
log.info(new ObjectMapper().writeValueAsString(result));
// 请求URL
log.info(request.getRequestURL().toString());
// 请求URI
log.info(request.getRequestURI());
// 创建时间
// operationLogEntity.setCreateTime(new Date());
// System.out.println(operationLogEntity);
log.info("环绕通知结束");
} catch (Exception e) {
}
return result;
}
/**
* 转换request 请求参数
* @param parameterMap request获取的参数数组
*/
public Map<String, String> convertParameterMap(Map<String, String[]> parameterMap) {
Map<String, String> convertParameterMap = new HashMap<>();
for (String key : parameterMap.keySet()) {
convertParameterMap.put(key, parameterMap.get(key)[0]);
}
return convertParameterMap;
}
}
6.测试
调用test方法,可以看到控制台已经打印出了日志信息,创建表的对象存入即可