面向切面编程AOP记录日志操作实现

本文介绍如何使用Spring AOP实现日志记录,通过自定义注解和切面编程,有效地分离关注点,降低代码耦合度,提升开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring AOP

OOP缺陷:在我们日常开发中常见Controller------>Service------>Dao------>数据库  自上而下的调用方式 这之中存在许多的缺陷和不足,我们在记录某个方法的操作详情时候,每个方法都要写对应的操作与业务逻辑结合,导致代码很臃肿耦合度很高。这个时候SpringAOP应运而生来解决我们出现的问题。

AOP应用场景:日志操作记录,权限,事务

日志操作记录

1.第一步倒入相应的maven坐标在IDEA环境中如果出现aspectjweaver对应的maven倒入不进来的话建议手动导入具体步骤如下

1)下载jar包: http://mvnrepository.com/artifact/org.aspectj/aspectjweaver 
2)倒入jar包: mvn install:install-file -Dfile=D:\psas_mvn\repository\org\aspectwever\aspectjweaver-1.9.4.jar -DgroupId=org.aspectj -DartifactId=aspectjweaver -Dversion=1.9.4 -Dpackaging=jar  路径替换成你自己的路径就可以了


 <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-aop</artifactId>
       <version>5.3.16</version>
 </dependency>
 <!-- aspectj支持 -->
 <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjrt</artifactId>
       <version>1.8.9</version>
 </dependency>
 <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjweaver</artifactId>
       <version>1.9.4</version>
 </dependency>
2.自定义注解 方面对不同的控制层Controller进行日志操作

@Target({ElementType.PARAMETER, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented
public @interface ControllerLog {

    String value() default "";
    String type() default "";
    
}
3.切面编程核心逻辑处理

@Aspect
@Component
public class LogAspect {

  // Controller层切点(声明切入点)
    @Pointcut("@annotation( com.unicom.tancms.config.ControllerLog)")
    public void controllerAspect() {
      }

    /**
     * 前置通知 用于拦截Controller层记录用户的操作
     * @param joinPoint 切点
     */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        getLog(joinPoint, null);
    }



private ActionLog getLog(JoinPoint joinPoint, Throwable e){
        HttpServletRequest request = getRequest();
        HttpSession session = request.getSession();

        // 读取session中的用户
        User user = (User) session.getAttribute("user");

        String userName=user.getRealName();//用户的真实姓名

        ActionLog log = new ActionLog();
        if(StringUtils.isNotBlank(userName)) {
            log.setUserName(userName);
        }
        log.setLogIp(IpUtil.getIpAdd(request));
        log.setUserId(user.getUserId());
        //log.setContent((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));
        //操作类型

        //操作URL
        log.setOperatorUrl(request.getRequestURI());
        //操作时间
        log.setOperatorTime(new Date());

        try {
            if(null == e){
                ControllerLog logAnnotation = getControllerAnnotation(joinPoint);
                log.setContent(logAnnotation.value());
                log.setOperatorType(logAnnotation.type()+"");
            }
            // 保存数据库
            logService.insertOperatorLog(log);
        } catch (Exception ex) {
            // 记录本地异常日志
            logger.error("==异常通知异常==");
            logger.error("异常信息:{}", ex.getMessage());
        }
        return log;
    }



/**
     * 获取注解中对方法的描述信息 用于Controller层注解
     * @param joinPoint 切点
     * @throws Exception
     */
    @SuppressWarnings("rawtypes")
    public static ControllerLog getControllerAnnotation(JoinPoint joinPoint) throws Exception {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        ControllerLog logAnnotation = null;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    logAnnotation = method.getAnnotation(ControllerLog.class);
                    break;
                }
            }
        }
        return logAnnotation;
    }

  public static HttpServletRequest getRequest() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        return request;
    }

}
   
@ControllerLog(value="查询数据",type="4") 可以对Controller进行控制哪个方法加日志记录

@Autowired
private TbUserService tbUserService;

@RequestMapping(value="/getPhoneMess",method= RequestMethod.POST)
@ControllerLog(value="查询数据",type="4")
public PageResult getPhoneMess(@RequestBody Map<String,Object> pageParams) {

	PageResult tbUserResult = tbUserService.getAllUser(pageParams);

	return tbUserResult;
}

 

4.注意,在SpringBoot项目中启动类要将该@EnableAspectJAutoProxy(proxyTargetClass = true)注解加如否则会报错代码如下:


@SpringBootApplication
@ComponentScan(basePackages ={"cn"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class SpringBootDemo {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemo.class);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值