注解
package com.ddb.common.annotation;
import org.omg.CORBA.DynAnyPackage.Invalid;
import javax.xml.crypto.Data;
import java.lang.annotation.*;
import java.time.LocalDateTime;
import static java.time.LocalDateTime.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {
String value();
boolean fail() default false;
boolean args() default true;
String operator() default "";
String name() default "";
String ip() default "";
int type() default 1;
}
切面类
package com.ddb.common.log;
import com.alibaba.fastjson.JSON;
import com.ddb.common.annotation.Log;
import com.ddb.model.result.Result;
import com.ddb.common.utils.LoginUserUtils;
import com.ddb.model.entity.DdbLog;
import com.ddb.service.DdbLogService;
import org.apache.commons.lang3.StringUtils;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.annotation.Order;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.concurrent.CompletableFuture;
@Order(2)
@Aspect
@Component
public class LogAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
@Autowired
DdbLogService ddbLogService;
@Pointcut("@annotation( com.ddb.common.annotation.Log)")
public void logPoinCut() {
}
@Around("logPoinCut()")
public Object saveSysLog(ProceedingJoinPoint joinPoint) throws Throwable {
LOGGER.debug("=========开始记录日志==========");
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
Log log = method.getAnnotation(Log.class);
String value = log.value();
LOGGER.debug("操作:{}", value);
DdbLog logAdd = new DdbLog();
logAdd.setOperation(value);
logAdd.setType(log.type());
Object[] args = joinPoint.getArgs();
LoginUserUtils.getUser()
.ifPresent(user -> {
LOGGER.debug("用户信息:{}", user);
logAdd.setOperatorName(user.getFullName());
logAdd.setUsername(user.getUsername());
logAdd.setIp(user.getIp());
});
if (StringUtils.isNotBlank(log.operator())) {
logAdd.setUsername(this.getSpelValue(log.operator(), method, args));
}
if (StringUtils.isNotBlank(log.name())) {
logAdd.setOperatorName(this.getSpelValue(log.name(), method, args));
}
logAdd.setOperateTime(LocalDateTime.now());
logAdd.setCreateTime(LocalDateTime.now());
final Object proceed;
try {
proceed = joinPoint.proceed();
LOGGER.debug("返回值:{}", JSON.toJSONString(proceed));
CompletableFuture.runAsync(()->ddbLogService.insert(logAdd));
return proceed;
} catch (Throwable throwable) {
throw throwable;
} finally {
LOGGER.debug("=========结束记录日志==========");
}
}
private String getSpelValue(String spel, Method method, Object[] args) {
try {
LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
String[] parameterNames = discoverer.getParameterNames(method);
if (null != parameterNames) {
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < parameterNames.length; i++) {
context.setVariable(parameterNames[i], args[i]);
}
return parser.parseExpression(spel).getValue(context, String.class);
}
} catch (Exception e) {
LOGGER.error("SPEL取值错误", e);
}
return spel;
}
private void buildOperatorStatus(LogAdd logAdd, Object proceed) {
try {
Result result = (Result) proceed;
if (HttpStatus.OK.value() == result.getCode()) {
logAdd.setOperatorStatus("成功");
logAdd.setRemark("");
} else {
logAdd.setOperatorStatus("失败");
logAdd.setRemark(result.getMessage());
}
} catch (Exception e) {
logAdd.setRemark(JSON.toJSONString(proceed));
}
}
}
实体类
package com.ddb.common.log;
;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigInteger;
import java.time.LocalDateTime;
@Data
@Api("新增系统日志")
public class LogAdd {
@ApiModelProperty("系统")
private String from;
@ApiModelProperty("ip")
private String ip;
@ApiModelProperty("使用人员")
private String operator;
@ApiModelProperty("操作者名称")
private String fullName;
@ApiModelProperty("操作名称")
private String operation;
@ApiModelProperty("操作状态")
private String operatorStatus;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("操作对象")
private String object;
@ApiModelProperty("操作时间")
private LocalDateTime operateTime;
}
package com.ddb.model.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.time.LocalDateTime;
import java.util.Date;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@ApiModel(value = "日志表")
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DdbLog {
@ApiModelProperty(value = "主键id")
private Integer id;
@ApiModelProperty(value = "ip")
private String ip;
@ApiModelProperty(value = "操作者名称")
private String operatorName;
@ApiModelProperty(value = "操作者账号")
private String username;
@ApiModelProperty(value = "操作名称")
private String operation;
@ApiModelProperty(value = "1是登录日志 2是操作日志")
private Integer type;
@ApiModelProperty(value = "操作时间")
private LocalDateTime operateTime;
@ApiModelProperty(value = "创建时间")
private LocalDateTime createTime;
}
使用方法
@Log(value = "登录系统", fail = true, operator = "#param.username", name = "#param.fullName", ip = "#param.ip",type = 1)
public Result loginSuccess(LoginUser param) {
return Result.build().ok();
}
@Log(value = "登录失败,不存在该用户", fail = true, operator = "#param.username", args = false,type = 1)
public Result loginFailNoUser( SignInDTO param, String msg) {
return Result.build().error().withMessage(msg);
}
@Log(value = "登录失败", fail = true, operator = "#param.username", args = false,type = 1)
public Result loginFail(DdbUser param, String msg) {
return Result.build().error().withMessage(msg);
}