• 通过AOP切面实现系统各个模块的用户操作记录


    需求:查看系统各个模块的用户操作记录,通过AOP切面实现,在不同模块的增删改接口上加切面注解

    部分示例代码如下,剩下的自行补充


    流程:
    1.根据配置确定是否启用用户操作记录。UserTraceAspectCondition:实现Condition接口的matches方法,根据配置文件决定是否初始化类
    2.切面配置类:AspectConfig 增加@Configuration和 @Bean注解,根据@Conditional注解来确定确认切面的执行条件。配置开启的话,实例化切面类;增加切面注解@interface OperateLog,定义UserTraceAspect切面类代表用户操作痕迹的服务类、操作模块、操作类型、操作内容等参数
    3.切面具体实现类:增加@Aspect注解,方法上增加@AfterReturning @AfterThrowing,分别在方法返回后执行切面方法或抛出异常后执行切面方法
    4.接口上增加@OperateLog切面注解,并指定该接口对应的模块参数和操作类型的参数、及根据切面处理用户的操作痕迹类(默认DefaultOperateLogServiceImpl)

    AspectConfig 切面配置类
    UserTraceAspect:用户操作痕迹切面类
    @annotation(operateLog)
    @interface OperateLog
    ApplicationContextUtil.getBean(operateLog.operateLogService()); 接口切面注解上对operateLogService进行了赋值
    注意点:处理切面的类分为正常返回对象的切面或者抛出异常的切面;处理用户操作记录的切面处理类的事务是新建的,不影响前面业务操作;切点JoinPoint 的.getArgs方法能从方法中或请求中获取参数值,如果以对象接口的,在方法中无法获取参数值,需要通过request.getParameter(parameter) 获取参数值

    UserTraceAspectCondition implements Condition{

    @Override

    publlic Boolean matches(conditionContext.getEnvironment().getProperty("ams.userTrace.use"))

    }

    @Configuration

    AspectConfig {

    @Bean

    @Conditional(UserTraceAspectCondition.class)

    public UserTraceAspect uerTraceAspect(){

        return new UserTraceAspect();

    }

    }

    切面注解

    @Target({ElementType.METHOD})

    @Retention(RetentionPolicy.RUNTIME)

    @Documented

    public @interface OperateLog {

    Class<? extends  OperateLogService> operateLogService() default  DefaultOperateLogServiceImpl.class;

    OperateModule operateModule();

    OperateType operateType();

    String operateContent() default "";

    boolean cover() default false;

    }

    切面类

    @Slf4j

    @Aspect

    UserTraceAspect {

    @AfterReturning(value = "@annotation(operateLog)",returning = "object")

    public void doAterReturning(JoinPoint joinPoint, OperateLog operateLog ,Object object)throws Throwable{

    try{

        OperateLogService operateLogService = ApplicationContextUtil.getBean(operateLog.operateLogService());

        operateLogService.process(joinPoint,getUserTraceDTO(operateLog),object);

    }catch (Exception e){

        log.warn("保存用户操作痕迹时发生异常:",e);

    }

    异常情况

    public  void doAfterThrowing(JoinPoint joinPoint, OperateLog operateLog, Throwable e) throws Throwable{

    try{

            OperateLogService operateLogService = ApplicationContextUtil.getBean(operateLog.operateLogService());

            operateLogService.process(joinPoint,getUserTraceDTO(operateLog),e);

        }catch (Exception e2){

            log.warn("保存用户操作痕迹时发生异常:",e2);

        }

    }

    @Service

    public class DefaultOperateLogServiceImpl extends AbstractOperateLogService{

    @Override

    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = Exception.class)

    public void process(JoinPoint joinPoint, UserTraceDTO userTraceDTO)throws Exception {

        super.process(joinPoint,userTraceDTO);

        setOperateContent(joinPoint,userTraceDTO);

        userTraceService.insert(userTraceDTO);

    }

    abstract class AbstractOperateLogService implements OperateLogService {

    @Override

    public void process(JoinPoint joinPoint, UserTraceDTO userTraceDTO) throws Exception{

        //默认成功

        userTraceDTO.setOperateResult(Boolean.TRUE);

        userTraceDTO.setUsername(SecurityUtils.getCurrentUsername());

        userTraceDTO.setOrganFullId(SecurityUtils.getCurrentOrgFullId());

        userTraceDTO.setOperateDate(new Date());

        userTraceDTO.setClassName(joinPoint.getSignature().getDeclaringTypeName());

        userTraceDTO.setMethodName(joinPoint.getSignature().getName());

    }

    @Slf4j
    @Service
    public class ConfigOperateLogServiceImpl extends AbstractOperateLogService{

    public Object getParameter(JoinPoint joinPoint,String parameter) throws Exception{

        // 参数值

        Object[] args = joinPoint.getArgs();

        // 参数名

        String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();

        //参数打印

        for (int i = 0,length = argNames.length;i<length;i++) {

            if (parameter.equals(argNames[i])){

                return args[i];

            }

        }

    //参数形式提交请求的,对象形式提交请求的需要以request

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        return request.getParameter(parameter);

    }

    对应用户模块接口上增加切面注解,默认执行DefaultOperateLogServiceImpl

    @OperateLog(operateModule = OperateModule.USER,operateType = OperateType.INSERT)
    @OperateLog(operateModule = OperateModule.USER,operateType = OperateType.UPDATE)
    @OperateLog(operateModule = OperateModule.USER,operateType = OperateType.DELETE)
    需要指定执行模块的加上operateLogService参数,做二次开发
    @OperateLog(operateLogService = ConfigOperateLogServiceImpl.class,operateModule = OperateModule.CONFIG,operateType = OperateType.UPDATE)

  • 相关阅读:
    关于自定义UICollectionViewLayout的一点个人理解<一>
    自定义进度条
    iOS 无限轮播图的两种实现
    图片的拉伸
    关于plist文件
    加载gif图过渡效果
    关于textView的字数限制
    php-fpm服务启动脚本
    转载:PHP支付宝接口RSA验证
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/renjiaqi/p/12418716.html
Copyright © 2020-2023  润新知