本文为小白快速上手SpingBoot+AOP日志记录demo,相关理论知识请移步百度。
话不多少,直接开始。
首先,我们创建一个简单的切点。
@Target({ElementType.PARAMETER,ElementType.METHOD}) //切面的切入点(方法)
@Retention(RetentionPolicy.RUNTIME) //切入的时间(运行时)
public @interface SystemLog(){
//操作类型
SystemLogEnum type();
/*
*要执行的操作,或者描述
*/
public String description() default "";
}
然后根据切点,来进行不同的处理。
@Component //自动注入
@Aspect
public class SysLogAspect{
@Pointcut("@annotation(com.xxx.xxx.SystemLog)")
public void logPointcut(){}
/*
*此处可以实现各种通知,前置通知,后置通知,环绕通知等。
*本例使用后置通知和异常通知
*/
//后置通知(带有两个参数,将在返回值返回时执行)
@AfterReturning(pointcut = "logPointcut()", returning = "jsonResult")
public void afterLog(JoinPoint joinPoint, Object jsonResult){
SysLog sysLog=warpSysLog(joinPoint);
//可根据业务需求对返回值进行处理。
System.out.println(JSON.toJSONString(jsonResult));
/*
*这里可以进行后续操作,入库或者传入队列
*/
}
//异常通知,当发生异常时触发
@AfterThrowing(value = "logPointcut()", throwing = "e")
public void throwingLog(JoinPoint joinPoint,Exception e){
SysLog sysLog=warpSysLog(joinPoint);
/*
*这里可以进行后续操作,入库或者传入队列
*/
}
public SysLog warpSysLog(JoinPoint joinPoint){
//获取请求响应对象
ServletRequestAttributes attributes=(ServletRequestAttributes)RequestContexHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
MethodSignature signature = (MethodSignature)joinPoint.getSignature();
SysLog sysLog= new SysLog();
//获取方法返回请求行中的参数部分(参数名+值)
//System.out.println(request.getQueryString());
sysLog.setParams(request.getQueryString());
//返回发出请求的客户机的完整主机名。
//System.out.println(request.getRemoteHost());
//返回发出请求的客户机的IP地址。
//System.out.println(request.getRemoteAddr());
//获取方法全路径
String methodName = signature.getDeclaringTypeName()+"."+signature.getName();
//获取注解参数值
SystemLog systemLog = signature.getMethod().getAnnotation(SysLog.class);
//获取注解的操作描述
String description=sysLog.description();
sysLog.setDescription(description);
//从header取出token(此处是在含有tocken的情况下,无tocken可不写。)
String token = request.getHeader("Authorization");
if (!StringUtils.isEmpty(token)) {
//操作人信息(根据tocken,获取tocken中的信息)
String username = JwtTokenUtil.getUsername(token);
String userRole = JwtTokenUtil.getUserRole(token);
sysLog.setUser_name(username);
sysLog.setUser_role(userRole);
}
if (!StringUtils.isEmpty(systemLog.type())){
sysLog.setType(systemLog.type().getType());
}
sysLog.setMethod(methodName);
sysLog.setCreate_time(new Date());
return sysLog;
}
}
因实际开发需要,本篇demo加入了token,无开发需要可忽略。
public class JwtTokenUtil {
/**
* 获得token中的信息无需secret解密也能获得
* @return token中包含的用户名
*/
public static String getUsername(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("userName").asString();
} catch (JWTDecodeException e) {
return null;
}
}
/**
* 获取登陆用户角色
* @param token
* @return
* 因业务需求,为一个用户多个角色
*/
//此处代码无法输入采用图片格式。
下面为日志实体类和枚举类
实体类
@ApiModel("日志实体类")
@Data
public class SysLog {
@ApiModelProperty("日志编号")
private String log_id;
@ApiModelProperty("用户名")
private String user_name;
@ApiModelProperty("用户权限")
private String user_role;
@ApiModelProperty("请求IP")
private String ip;
@ApiModelProperty("操作描述")
private String description;
@ApiModelProperty("传入参数")
private String params;
@ApiModelProperty("用户浏览器")
private String browser;
@ApiModelProperty("执行时间")
private String time;
@ApiModelProperty("日志类型")
private String type;
@ApiModelProperty("执行方法")
private String method;
@ApiModelProperty("创建时间")
private Date create_time;
@ApiModelProperty("异常详细信息")
private String exception_detail;
}
枚举类
public enum SystemLogEnum {
//可自行添加修改
SAVE_LOG("添加"),
UPDATE_LOG("修改"),
SELECT_LOG("查询"),
DELETE_LOG("删除"),
REGISTER_LOG("注册"),
LOGIN_LOG("登录"),
OPERATION_LOG("操作"),
THROW_LOG("异常");
private String type;
SystemLogEnum(String type) {
this.type = type;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
使用方法,可以直接在方法上进行注解。
@SystemLog(description = "测试message",type = SystemLogEnum.OPERATION_LOG)
public void test(String message) {
System.out.println(message);
}
到此,小伙伴就可以愉快的进行日志记录开发了~~~
初次发布,如有问题,请多多包涵。