自定义注解生成操作日志

1. 创建自定义注解

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationDetail {

    /**
     * 方法描述
     */
    String detail() default "";

    /**
     * 日志操作级别
     */
    int level() default 0;

    /**
     * 操作了类型,默认为未知
     */
    OperationType operationType() default  OperationType.UNKNOWN;

    /**
     * 操作对象,默认为未知
     */
    OperationUnit operationUnit() default  OperationUnit.UNKNOWN;

    /**
     * 操作人
     */
    String operator() default "UNKNOWN" ;



}

上面代码用到的枚举类

public enum OperationType {

    /**
     * 操作类型
     */
    UNKNOWN("unknown"),
    DELETE("delete"),
    SELECT("select"),
    UPDATE("update"),
    INSERT("insert");

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    OperationType(String s) {
        this.value = s;
    }
}
public enum OperationUnit {

    /**
     * 被操作的单元
     */
    UNKNOWN("unknown"),
    DELETE("delete"),
    SELECT("select"),
    UPDATE("update"),
    INSERT("insert"),
    // 导出
    EXPORT("export"),
    // 下载
    DOWNLOAD("download"),
    // 修改密码
    UPDATE_PASSWORD("update_password"),
    // 登录
    LOGIN_SYSTEM("login"),
    // 退出登录
    LOGOUT("logout");

    private String value;

    OperationUnit(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

2.创建切面

@Slf4j
@Aspect
@Component
public class OperationLogAspect {

    @Autowired
    ApplicationContext applicationContext;

    OperationLogRecordService operationLogRecordService;

    /**
     * 注解方式的切点
     */
    @Pointcut("@annotation(com.c2m.log.annotation.OperationDetail)")
    public void operationDetail(){}

    /**
     *环绕增强
     * @return
     */
    @Around("operationDetail()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws  Throwable{
        Object res = null;
        JSONObject json = new JSONObject();
        try {
            json = this.resolvingArgs(joinPoint);
            res = joinPoint.proceed();
            json.put("requestResult", res);
            return res;
        }finally {
            try{
                operationLogRecordService = applicationContext.getBean(OperationLogRecordService.class);
                operationLogRecordService.record(json);
            }catch (NoSuchBeanDefinitionException e){
                log.info("操作日志:"+json.toJSONString());
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private JSONObject resolvingArgs(ProceedingJoinPoint joinPoint){
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        OperationDetail annotation = signature.getMethod().getAnnotation(OperationDetail.class);
        String methodName,operationType,operationUnit,operationDetail,operator;
        // 方法名称
        methodName = signature.getMethod().getName();
        // 操作类型("insert、delete、update、select")
        operationType = annotation.operationType().getValue();
        // 业务功能("用户登陆、审核信息、导出文件、删除用户···")
        operationUnit = annotation.operationUnit().getValue();
        // 操作描述
        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
        operationDetail = this.replaceParams(argNames, joinPoint.getArgs(), annotation.detail());
        //操作人
        operator = this.replaceParams(argNames, joinPoint.getArgs(), annotation.operator());
        // 请求参数
        Object[] objects = joinPoint.getArgs();
        String params = "";
        if (objects.length > 0) {
            if (objects[0] instanceof String) {
                params = objects[0].toString();
            } else {
                params = JSONObject.toJSONString(objects[0]);
            }
        }
        Map<String,Object> resMap = new HashMap<>();
        resMap.put("requestParameters",params);
        resMap.put("methodName",methodName);
        resMap.put("operationType",operationType);
        resMap.put("operationUnit",operationUnit);
        resMap.put("operationDetail",operationDetail);
        resMap.put("operator",operator);
        return new JSONObject(resMap);
    }

    /**
     * 对当前登录用户和占位符处理
     *
     * @param argNames 方法参数名称数组
     * @param args 方法参数数组
     * @param str 被替换的字符串
     * @return
     */
    private String replaceParams(String[] argNames,Object[] args,String str){
        Map<Object, Object> map = new HashMap<>(5);
        for(int i = 0;i < argNames.length;i++){
            map.put(argNames[i],args[i]);
        }
        try {
            for (Map.Entry<Object, Object> entry : map.entrySet()) {
                Object k = entry.getKey();
                Object v = entry.getValue();
                str = str.replace("$"+k, JSON.toJSONString(v));
            }
            str = str.replaceAll("\"","");
        }catch (Exception e){
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before("operationDetail()")
    public void doBeforeAdvice(JoinPoint joinPoint){
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        log.info("进入"+signature.getMethod()+"方法前执行.....");

    }

    /**
     * 处理完请求,返回内容
     * @param res
     */
    @AfterReturning(returning = "res", pointcut = "operationDetail()")
    public void doAfterReturning(Object res) {
        log.info("方法的返回值 : " + res);
    }

    /**
     * 后置异常通知
     */
    @AfterThrowing("operationDetail()")
    public void throwsException(JoinPoint joinPoint){
        log.info("方法异常时执行.....");
    }


    /**
     * 后置最终通知,final增强,不管是抛出异常或者正常退出都会执行
     */
    @After("operationDetail()")
    public void after(JoinPoint joinPoint){
        log.info("方法最后执行.....");
    }
}

3. 这里有一个operationLogRecordService,代码如下:

public interface OperationLogRecordService {

    /**
     * 记录日志
     */
    void record(JSONObject json);
}

4.使用方式

在方法上加上这个注解

@OperationDetail(detail = "修改密码", operationUnit = OperationUnit.UPDATE_PASSWORD,operationType = OperationType.UPDATE,operator = "$userName")
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值