通过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)

 

 

posted @ 2020-03-05 10:16  LZ太热  阅读(736)  评论(0编辑  收藏  举报