代码拉取完成,页面将自动刷新
一、引言 阐述日志审计在保证系统安全、追踪操作行为、满足合规要求等方面的关键作用,并指出为何选用SLF4J作为统一日志接口,以及 Aspect作为具体的日志实现框架来完成日志审计功能。
模块介绍
附上对应demo 地址:
二、SLF4J与Aspect简介
三、利用Aspect实现日志审计功能
* 日志切面类上应有@Aspect注解。
* 切面方法的切入点表达式应能匹配到模块A和B中的Controller方法,例如:Java
@Pointcut*("execution (* com.demo.demob.controller..*.*(..)) || " +
"execution (* com.demo.demoa.controller..*.*(..)) ||" +
"@annotation(com.demo.log.OperLog)")
* 确保公共模块作为依赖被正确地引入到模块A和B中。
1 启用Spring AOP代理: 在模块A和B的Spring Boot应用主类上添加@EnableAspectJAutoProxy注解来启用AOP代理。
2 确保拦截器工作正常:
3 在线程局部存储中传递日志信息:
四、核心代码
1.切面注解
package com.demo.log;
import java.lang.annotation.*;
/**
* @author zzz
* @pack_name com.mw.core.log
* @project_name mcloud
* @date 2024/3/25 11:03:40
* @Description 注解操作
*/
@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface OperLog {
String operModul() default ""; // 操作模块
String operType() default ""; // 操作类型
String operDesc() default ""; // 操作说明
}
在controller中 ,使用 @OperLog 记录操作的模块,内容等记录
@GetMapping("/test")
@OperLog(operType = "测试", operDesc = "切面内容测试a")
public String test() {
return "HelloController.test------a";
}
@Pointcut注解用于定义一个切入点(Pointcut)
@Pointcut("@annotation(com.demo.log.OperLog)")
public void operLogPointCut() {
}
@AfterReturning 通知 pointcut 填写切入
@AfterReturning(pointcut = "operLogPointCut()", returning = "keys")
public JSONObject saveOperLog(JoinPoint joinPoint, Object keys) {
// 具体增强内容。包含日志等。 具体代码参照 demo-log包内OperLogAspect类
//伪代码
// 获取RequestAttributes
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = (HttpServletRequest) requestAttributes
.resolveReference(RequestAttributes.REFERENCE_REQUEST);
// 请求路径
String requestURI = request.getRequestURI();
// 请求路径
logEntity.setFUrl(requestURI);
// 主机地址
String host = request.getRemoteAddr();
// 获取日志注解的@OperLog的内容
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
Method method = signature.getMethod();
// 获取操作 添加在controller上的@OperLog
OperLog opLog = method.getAnnotation(OperLog.class);
logEntity.setFTitle(opLog.operDesc());
// 当然,如果项目使用了 swagger或者增强knife4j-openapi3-spring-boot-starter
//通过 反射获取 接口文档提供的注解 。获取接口文档里面的内容。获取 @ApiMethod 中的内容。完善日志记录内容
/**
* @ApiMethod(desc = "审批回调相关业务接口:",
* outerPath = "/{groupId}/callback",
* innerPath = "/{groupId}/callback")
*/
// 从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取切入点所在的方法
ApiOperation annotation = method.getAnnotation(ApiOperation.class);
// 最后 将处理内容设置到 本地线程上线文中
ThreadUitl.set("log",logEntity )
}
具体代码参照 demo-log包内OperLogAspect类
2.日记记录
package com.demo.demoa.interctor;
import com.alibaba.fastjson2.JSONObject;
import com.demo.util.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* @author zzz
* @pack_name com.demo.demoa.interctor
* @project_name Log-Auit
* @date 2024/3/26 14:03:54
* @Description 全局拦截器
*/
@Component
@Slf4j
public class GlobalInterctor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
/**
* demo A 日记记录。
* 因为是跨应用获取日志。这里采用本地线程获取上下文 通过ThreadLocalUtil.get("log")获取
*/
JSONObject logEntity = (JSONObject)ThreadLocalUtil.get("log");
if (logEntity !=null){
// 可以记录进数据库
log.info("日志记录-===========》:{}",logEntity.toJSONString());
}
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
package com.demo.demoa.config;
import com.demo.demoa.interctor.GlobalInterctor;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author zzz
* @pack_name com.demo.demoa
* @project_name Log-Auit
* @date 2024/3/26 15:03:03
* @Description
*/
@Configuration
@RequiredArgsConstructor
public class CustomWebConfig implements WebMvcConfigurer {
private final GlobalInterctor globalInterctor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(globalInterctor).addPathPatterns("/**");
}
}
@Pointcut("execution (* com.demo.demob.controller..*.*(..)) || " +
"execution (* com.demo.demoa.controller..*.*(..))
public void operLogPointCut() {
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。