package com.kidgrow.log.aspect; import com.kidgrow.log.annotation.AuditLog; import com.kidgrow.log.model.Audit; import com.kidgrow.log.properties.AuditLogProperties; import com.kidgrow.log.service.IAuditService; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.core.DefaultParameterNameDiscoverer; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; /** * 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020
* * @Description: 审计日志切面
* @Project:
* @CreateDate: Created in 2020/2/27 09:22
* @Author: liuke */ @Slf4j @Aspect @EnableConfigurationProperties(AuditLogProperties.class) @ConditionalOnClass({HttpServletRequest.class, RequestContextHolder.class}) public class AuditLogAspect { @Value("${spring.application.name}") private String applicationName; @Autowired private AuditLogProperties auditLogProperties; @Autowired(required = false) private IAuditService auditService; // public AuditLogAspect(AuditLogProperties auditLogProperties, IAuditService auditService) { // this.auditLogProperties = auditLogProperties; // this.auditService = auditService; // } /** * 用于SpEL表达式解析. */ private SpelExpressionParser spelExpressionParser = new SpelExpressionParser(); /** * 用于获取方法参数定义名字. */ private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer(); @Before("@within(auditLog) || @annotation(auditLog)") public void beforeMethod(JoinPoint joinPoint, AuditLog auditLog) { //判断功能是否开启 if (auditLogProperties.getEnabled()) { if (auditService == null) { log.warn("AuditLogAspect - auditService is null"); return; } if (auditLog == null) { // 获取类上的注解 auditLog = joinPoint.getTarget().getClass().getDeclaredAnnotation(AuditLog.class); } Audit audit = getAudit(auditLog, joinPoint); auditService.save(audit); } } /** * 解析spEL表达式 */ private String getValBySpEL(String spEL, MethodSignature methodSignature, Object[] args) { //获取方法形参名数组 String[] paramNames = nameDiscoverer.getParameterNames(methodSignature.getMethod()); if (paramNames != null && paramNames.length > 0) { Expression expression = spelExpressionParser.parseExpression(spEL); // spring的表达式上下文对象 EvaluationContext context = new StandardEvaluationContext(); // 给上下文赋值 for(int i = 0; i < args.length; i++) { context.setVariable(paramNames[i], args[i]); } return expression.getValue(context).toString(); } return null; } /** * 构建审计对象 */ private Audit getAudit(AuditLog auditLog, JoinPoint joinPoint) { Audit audit = new Audit(); audit.setTimestamp(LocalDateTime.now()); audit.setApplicationName(applicationName); MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature(); audit.setClassName(methodSignature.getDeclaringTypeName()); audit.setMethodName(methodSignature.getName()); ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String userId = request.getHeader("x-userid-header"); String userName = request.getHeader("x-user-header"); String clientId = request.getHeader("x-client-header"); audit.setUserId(userId); audit.setUserName(userName); audit.setClientId(clientId); String operation = auditLog.operation(); if (operation.contains("#")) { //获取方法参数值 Object[] args = joinPoint.getArgs(); operation = getValBySpEL(operation, methodSignature, args); } audit.setOperation(operation); return audit; } }