Browse Source

日志管理 - 日志记录注解型全局拦截器

caozixuan 3 năm trước cách đây
mục cha
commit
6c1fc1adaa

+ 2 - 0
distributed-print/src/main/java/com/qmth/distributed/print/api/TeachCourseController.java

@@ -4,6 +4,7 @@ import com.qmth.boot.api.constant.ApiConstant;
 import com.qmth.distributed.print.business.bean.params.TeachCourseParams;
 import com.qmth.distributed.print.business.bean.result.EditResult;
 import com.qmth.distributed.print.business.service.TeachCourseService;
+import com.qmth.teachcloud.common.annotation.OperationLogDetail;
 import com.qmth.teachcloud.common.contant.SystemConstant;
 import com.qmth.teachcloud.common.entity.SysUser;
 import com.qmth.teachcloud.common.util.Result;
@@ -37,6 +38,7 @@ public class TeachCourseController {
     @ApiOperation(value = "教学课程-查询")
     @RequestMapping(value = "/page", method = RequestMethod.POST)
     @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
+    @OperationLogDetail
     public Result findTeachCoursePage(@ApiParam(value = "课程名称(模糊查询)") @RequestParam(required = false) String courseName,
                                       @ApiParam(value = "分页页码", required = true) @RequestParam @Min(SystemConstant.PAGE_NUMBER_MIN) Integer pageNumber,
                                       @ApiParam(value = "分页数", required = true) @RequestParam @Min(SystemConstant.PAGE_SIZE_MIN) @Max(SystemConstant.PAGE_SIZE_MAX) Integer pageSize) {

+ 44 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/annotation/OperationLogDetail.java

@@ -0,0 +1,44 @@
+package com.qmth.teachcloud.common.annotation;
+
+import com.qmth.teachcloud.common.enums.log.LevelEnum;
+import com.qmth.teachcloud.common.enums.log.OperationTypeEnum;
+import com.qmth.teachcloud.common.enums.log.OperationUnitEnum;
+import com.qmth.teachcloud.common.enums.log.SystemEnum;
+
+import java.lang.annotation.*;
+
+/**
+ * @Description: 操作日志注解
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+@Documented
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface OperationLogDetail {
+
+    /**
+     * 日志记录 - 具体操作的内容(默认为空)
+     */
+    String detail() default "";
+
+    /**
+     * 日志记录 - 日志等级(默认为第四级(普通信息))
+     */
+    LevelEnum level() default LevelEnum.QUATERNARY;
+
+    /**
+     * 日志记录 - 操作类型(主要是 'SELECT,EDIT,DELETE',默认为'未知')
+     */
+    OperationTypeEnum operationType() default OperationTypeEnum.UN_KNOW;
+
+    /**
+     * 日志记录 - 被操作对象(主要是表,默认为'未知')
+     */
+    OperationUnitEnum operationUnit() default OperationUnitEnum.UN_KNOW;
+
+    /**
+     * 日志记录 - 被记录日志的系统(默认为'分布式印刷系统')
+     */
+    SystemEnum system() default SystemEnum.DISTRIBUTED_PRINT;
+}

+ 161 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/aspect/LogAspect.java

@@ -0,0 +1,161 @@
+package com.qmth.teachcloud.common.aspect;
+
+import com.alibaba.fastjson.JSON;
+import com.qmth.teachcloud.common.annotation.OperationLogDetail;
+import com.qmth.teachcloud.common.contant.SystemConstant;
+import com.qmth.teachcloud.common.entity.BasicOperationLog;
+import com.qmth.teachcloud.common.entity.SysUser;
+import com.qmth.teachcloud.common.util.ServletUtil;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.*;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Description: 日志操作记录拦截aop
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+@Aspect
+@Component
+public class LogAspect {
+
+    private final static Logger log = LoggerFactory.getLogger(LogAspect.class);
+
+    /**
+     * 日志注解切入点
+     */
+    @Pointcut("@annotation(com.qmth.teachcloud.common.annotation.OperationLogDetail)")
+    public void operationLog(){
+
+    }
+
+    /**
+     * 环绕增强,操作日志环绕切入
+     * @param joinPoint joinPoint
+     * @return return
+     * @throws Throwable Throwable
+     */
+    @Around(value = "operationLog()")
+    public Object aroundOperationLogPoint(ProceedingJoinPoint joinPoint) throws Throwable {
+        Object res = null;
+        long time = System.currentTimeMillis();
+        try {
+            res =  joinPoint.proceed();
+            time = System.currentTimeMillis() - time;
+            return res;
+        } finally {
+            try {
+                //方法执行完成后增加日志
+                addOperationLog(joinPoint,res,time);
+            }catch (Exception e){
+                System.out.println("LogAspect 操作失败:" + e.getMessage());
+                e.printStackTrace();
+            }
+        }
+    }
+
+    /**
+     * 记录日志操作
+     * @param joinPoint joinPoint
+     * @param res 返回值
+     * @param time 方法执行时间
+     */
+    private void addOperationLog(JoinPoint joinPoint, Object res, long time){
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
+        String userName = requestUser.getRealName();
+
+        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
+        BasicOperationLog operationLog = new BasicOperationLog();
+
+        // 方法中的信息
+        operationLog.setId(SystemConstant.getDbUuid());
+        operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
+        operationLog.setArgs(JSON.toJSONString(joinPoint.getArgs()));
+        operationLog.setRunTime(time);
+        operationLog.setReturnValue(JSON.toJSONString(res));
+        operationLog.setUserId(requestUser.getId());
+        operationLog.setUserName(userName);
+        operationLog.setCreateTime(new Date().getTime());
+
+        // 注解中的信息
+        OperationLogDetail annotation = signature.getMethod().getAnnotation(OperationLogDetail.class);
+        if(annotation != null){
+            operationLog.setDetail(getDetail(((MethodSignature)joinPoint.getSignature()).getParameterNames(),joinPoint.getArgs(),annotation));
+            operationLog.setLevel(annotation.level());
+            operationLog.setOperationType(annotation.operationType());
+            operationLog.setOperationUnit(annotation.operationUnit());
+            operationLog.setSystemType(annotation.system());
+        }
+        //TODO 这里保存日志
+        System.out.println(JSON.toJSONString(operationLog));
+    }
+
+    /**
+     * 对当前登录用户和占位符处理
+     * @param argNames 方法参数名称数组
+     * @param args 方法参数数组
+     * @param annotation 注解信息
+     * @return 返回处理后的描述
+     */
+    private String getDetail(String[] argNames, Object[] args, OperationLogDetail annotation){
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
+
+        Map<Object, Object> map = new HashMap<>();
+        for(int i = 0;i < argNames.length;i++){
+            map.put(argNames[i],args[i]);
+        }
+
+        String detail = annotation.detail();
+        try {
+            detail = "'" + requestUser.getRealName() + "'=》" + annotation.detail();
+            for (Map.Entry<Object, Object> entry : map.entrySet()) {
+                Object k = entry.getKey();
+                Object v = entry.getValue();
+                detail = detail.replace("{{" + k + "}}", JSON.toJSONString(v));
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return detail;
+    }
+
+    @Before(value = "operationLog()")
+    public void doBeforeAdvice(JoinPoint joinPoint){
+        System.out.println("进入方法前执行.....");
+
+    }
+
+    /**
+     * 处理完请求,返回内容
+     * @param ret ret
+     */
+    @AfterReturning(returning = "ret", pointcut = "operationLog()")
+    public void doAfterReturning(Object ret) {
+        System.out.println("方法的返回值 : " + ret);
+    }
+
+    /**
+     * 后置异常通知
+     */
+    @AfterThrowing(value = "operationLog()")
+    public void throwss(JoinPoint jp){
+        System.out.println("方法异常时执行.....");
+    }
+
+
+    /**
+     * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
+     */
+    @After(value = "operationLog()")
+    public void after(JoinPoint jp){
+        System.out.println("方法最后执行.....");
+    }
+}

+ 169 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/entity/BasicOperationLog.java

@@ -0,0 +1,169 @@
+package com.qmth.teachcloud.common.entity;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.qmth.teachcloud.common.enums.log.LevelEnum;
+import com.qmth.teachcloud.common.enums.log.OperationTypeEnum;
+import com.qmth.teachcloud.common.enums.log.OperationUnitEnum;
+import com.qmth.teachcloud.common.enums.log.SystemEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import java.io.Serializable;
+
+/**
+ * @Description: 基础日志记录表
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+@ApiModel(value = "BasicOperationLog对象", description = "基础日志记录表")
+public class BasicOperationLog implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long id;
+
+    @ApiModelProperty(value = "日志详情")
+    private String detail;
+
+    @ApiModelProperty(value = "日志等级(PRIMARY(\"一级日志:敏感信息\"),SECONDARY(\"二级日志:重要信息\"),TERTIARY(\"三级日志:次要信息\"),QUATERNARY(\"四级日志:普通信息\"))")
+    private LevelEnum level;
+
+    @ApiModelProperty(value = "操作类型(UN_KNOW(\"未知\"),SELECT(\"查询\"),EDIT(\"新增或更新\"),DELETE(\"删除\"))")
+    private OperationTypeEnum operationType;
+
+    @ApiModelProperty(value = "操作对象(略)")
+    private OperationUnitEnum operationUnit;
+
+    @ApiModelProperty(value = "日志系统类型")
+    private SystemEnum systemType;
+
+    @ApiModelProperty(value = "方法url")
+    private String method;
+
+    @ApiModelProperty(value = "参数")
+    private String args;
+
+    @ApiModelProperty(value = "方法运行时间")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long runTime;
+
+    @ApiModelProperty(value = "方法返回值")
+    private String returnValue;
+
+    @ApiModelProperty(value = "用户对象id")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long userId;
+
+    @ApiModelProperty(value = "用户名称")
+    private String userName;
+
+    @ApiModelProperty(value = "日志记录时间")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long createTime;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getDetail() {
+        return detail;
+    }
+
+    public void setDetail(String detail) {
+        this.detail = detail;
+    }
+
+    public LevelEnum getLevel() {
+        return level;
+    }
+
+    public void setLevel(LevelEnum level) {
+        this.level = level;
+    }
+
+    public OperationTypeEnum getOperationType() {
+        return operationType;
+    }
+
+    public void setOperationType(OperationTypeEnum operationType) {
+        this.operationType = operationType;
+    }
+
+    public OperationUnitEnum getOperationUnit() {
+        return operationUnit;
+    }
+
+    public void setOperationUnit(OperationUnitEnum operationUnit) {
+        this.operationUnit = operationUnit;
+    }
+
+    public SystemEnum getSystemType() {
+        return systemType;
+    }
+
+    public void setSystemType(SystemEnum systemType) {
+        this.systemType = systemType;
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public void setMethod(String method) {
+        this.method = method;
+    }
+
+    public String getArgs() {
+        return args;
+    }
+
+    public void setArgs(String args) {
+        this.args = args;
+    }
+
+    public Long getRunTime() {
+        return runTime;
+    }
+
+    public void setRunTime(Long runTime) {
+        this.runTime = runTime;
+    }
+
+    public String getReturnValue() {
+        return returnValue;
+    }
+
+    public void setReturnValue(String returnValue) {
+        this.returnValue = returnValue;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public Long getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Long createTime) {
+        this.createTime = createTime;
+    }
+}

+ 40 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/log/LevelEnum.java

@@ -0,0 +1,40 @@
+package com.qmth.teachcloud.common.enums.log;
+
+import java.util.Objects;
+
+/**
+ * @Description: 日志等级枚举类
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+public enum LevelEnum {
+    PRIMARY("一级日志:敏感信息"),
+    SECONDARY("二级日志:重要信息"),
+    TERTIARY("三级日志:次要信息"),
+    QUATERNARY("四级日志:普通信息"),
+    ;
+    private final String desc;
+
+    LevelEnum(String desc) {
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param p desc
+     * @return name
+     */
+    public static String convertToName(String p) {
+        for (LevelEnum e : LevelEnum.values()) {
+            if (Objects.equals(p, e.getDesc())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+}

+ 39 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/log/OperationTypeEnum.java

@@ -0,0 +1,39 @@
+package com.qmth.teachcloud.common.enums.log;
+
+import java.util.Objects;
+
+/**
+ * @Description: 操作类型枚举
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+public enum OperationTypeEnum {
+    UN_KNOW("未知"),
+    SELECT("查询"),
+    EDIT("新增或更新"),
+    DELETE("删除");
+    private final String desc;
+
+    OperationTypeEnum(String desc) {
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param p desc
+     * @return name
+     */
+    public static String convertToName(String p) {
+        for (OperationTypeEnum e : OperationTypeEnum.values()) {
+            if (Objects.equals(p, e.getDesc())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+}

+ 44 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/log/OperationUnitEnum.java

@@ -0,0 +1,44 @@
+package com.qmth.teachcloud.common.enums.log;
+
+import java.util.Objects;
+
+/**
+ * @Description: 被操作对象枚举类
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+public enum OperationUnitEnum {
+    UN_KNOW("未知", ""),
+    TEACH_COURSE("操作'teach_course'表", "teach_course"),
+    ;
+    private final String desc;
+    private final String table;
+
+    OperationUnitEnum(String desc, String table) {
+        this.desc = desc;
+        this.table = table;
+    }
+
+    public String getTable() {
+        return table;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param p desc
+     * @return name
+     */
+    public static String convertToName(String p) {
+        for (OperationUnitEnum e : OperationUnitEnum.values()) {
+            if (Objects.equals(p, e.getDesc())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+}

+ 38 - 0
teachcloud-common/src/main/java/com/qmth/teachcloud/common/enums/log/SystemEnum.java

@@ -0,0 +1,38 @@
+package com.qmth.teachcloud.common.enums.log;
+
+import java.util.Objects;
+
+/**
+ * @Description: 日志系统枚举
+ * @Author: CaoZixuan
+ * @Date: 2022-02-14
+ */
+public enum SystemEnum {
+    DISTRIBUTED_PRINT("分布式印刷系统日志"),
+    TEACH_CLOUD_REPORT("教研分析系统日志"),
+    ;
+    private final String desc;
+
+    SystemEnum(String desc) {
+        this.desc = desc;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    /**
+     * 状态转换 toName
+     *
+     * @param p desc
+     * @return name
+     */
+    public static String convertToName(String p) {
+        for (SystemEnum e : SystemEnum.values()) {
+            if (Objects.equals(p, e.getDesc())) {
+                return e.name();
+            }
+        }
+        return null;
+    }
+}