springboot使用aop切面,记录日志
技术说明:
springboot:2.1.4.RELEASE
jQuery
Ajax
mysql:8.0.32
业务背景:
当我们在操作网页的时候,我们后台需要记录每个用户,什么时候操作了哪些记录。比如注册了,还是登录了,还是查询了,我们把这些记录全部储存起来,方便管理员查看。
pom.xml
<!--日志记录-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.25.1</version>
</dependency>
<!--aop切面,方便记录日志-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
首先定义一个AopContextUtil工具类,里面包含一些常用方法,比如记录用户访问的ip
public class AopContextUtil {
/**
* 入参数据
* @param joinPoint
* @param request
* @return
*/
public static String preHandle(JoinPoint joinPoint, HttpServletRequest request) {
String reqParam = "";
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method targetMethod = methodSignature.getMethod();
Annotation[] annotations = targetMethod.getAnnotations();
for (Annotation annotation : annotations) {
//此处可以改成自定义的注解
if (annotation.annotationType().equals(RequestMapping.class)) {
reqParam = JSON.toJSONString(request.getParameterMap());
break;
}
}
return reqParam;
}
/**
* 获取IP地址的方法
*
* @param request 传一个request对象下来
* @return
*/
public static String getIpAddress(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
}
定义切面类,就是哪些类哪些方法,需要被记录
@Aspect
@Component
@Slf4j
public class CommonAspect {
@Autowired
private LogsService logsService;//这是一个日志service层,用来插入到日志数据表里面
/**
* 定义切点 @Pointcut
*/
@Pointcut("execution(* com.yuanshengrong.springbootyuanshengrong.controller.*.*(..))")//这里定义的是在这个目录下的controller包下的所有类,所有方法都被记录,就是当用户触发了这个类,这个方法,那就记录下来,用户发起了什么请求。
public void log(){
}
/**
* ProceedingJoinPoint仅支持@Around
*/
@AfterReturning("log()")
public void saveOperation(JoinPoint joinPoint){
log.info("---------------接口日志记录---------------");
// 创建一个日志对象(准备记录日志)
LogsDo logsDo = new LogsDo();
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
//IP地址
String ipAddr = AopContextUtil.getIpAddress(request);//AopContextUtil前面有定义,获取ip的
logsDo.setClientip(ipAddr);
//url
String url = request.getRequestURL().toString();//用户发起的请求链接
logsDo.setOperurl(url);
//请求参数
/* String reqParam =AopContextUtil.preHandle(joinPoint,request);
logsDo.setReqparam(reqParam);*/
// 1.方法执行前的处理,相当于前置通知
// 获取方法签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
// 获取方法上面的注解
LogAnno logAnno = method.getAnnotation(LogAnno.class);
if (logAnno !=null){
// 获取操作描述的属性值
String operateType = logAnno.operateType();
// 保存操作说明
logsDo.setOpertype(operateType);
}
//TODO 设置操作人,从session中获取。
String username = (String)request.getSession().getAttribute("username");//从session中获取用户名,记录是哪个用户操作的
//保存用户名到数据库
logsDo.setUsername(username);
// 设置操作日期
logsDo.setOpertime(new Date());
logsService.insertSelective(logsDo);
}
}
@Target(ElementType.METHOD) // 方法注解
@Retention(RetentionPolicy.RUNTIME) // 运行时可见
public @interface LogAnno {
String operateType();// 记录日志的操作类型
}
上面这个代码,是用来记录日志的,我们只需要在方法上加上@LogAnno(operateType = "导出面试信息Excel记录"),用来记录操作的日志类型即可


浙公网安备 33010602011771号