一、AOP介绍

        Spring Boot AOP可以用来拦截Controller中的方法,实现对请求的统一处理。通过定义切面和切点,可以在请求前、后、异常等不同的阶段进行处理,比如记录日志、权限校验、参数校验等。在Spring Boot中,可以使用@Aspect注解定义切面,使用@Pointcut注解定义切点,使用@Before、@After、@Around等注解定义不同类型的通知。同时,还可以使用@Order注解指定切面的执行顺序

二、代码

 数据表对应的实体类

package com.ruoyi.car.aop;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * 操作日志表
 * */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AdminLog implements Serializable {

    private static final long serialVersionUID = 7925874058046995566L;

    private Long carRecordId;//用车记录id
    private Long operationBy;//用户id 操作人ID
    private Long carinfoId;//车辆信息id
    private Long useinfoId;//车辆申请id
    private String userName;//用户名称
    private String operationName;//操作内容
    private String operationTime;//操作时间
    private String carName;
    private String color;
    private String carNumber;
}

自定义注解类

package com.ruoyi.car.aop;

import java.lang.annotation.*;

/**
 * 配置自定义log注解类
 */
@Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
@Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
@Documented 
public @interface MyLog {
    String operation () default "";
}

aspect切面类

package com.ruoyi.car.aop;
import com.ruoyi.car.domain.CarInfo;
import com.ruoyi.car.domain.CarUseInfo;
import com.ruoyi.car.mapper.CarInfoMapper;
import com.ruoyi.car.mapper.MyLogMapper;
import com.ruoyi.car.service.ICarUseRecordService;
import com.ruoyi.car.vo.CarInfoAndUser;
import com.ruoyi.common.core.domain.entity.SysUser;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


/** 系统日志:切面处理类 */
@Aspect
@Component
public class SysLogAspect {


    /**操作数据库 */
    @Autowired
    private MyLogMapper myLogMapper;

    @Autowired
    private CarInfoMapper carInfoMapper;

    @Autowired
    private ICarUseRecordService carUseRecordService;

    //定义切点 @Pointcut
    //在注解的位置切入代码
    @Pointcut("@annotation(com.ruoyi.car.aop.MyLog)")
    public void logPoinCut() {
    }

    //切面 配置通知
    @Before("logPoinCut()")
    public void saveOperation(JoinPoint joinPoint) {

    }
    @After("logPoinCut()")
    public void saveOperationAfter(JoinPoint joinPoint) {
        //用于保存操作日志
        AdminLog adminLog = new AdminLog();

        //存放所有记录的集合
        List<AdminLog> adminLogs = new ArrayList<>();

        //从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();

        //获取切入点所在的方法
        Method method = signature.getMethod();
        // 请求的方法参数值
        Object[] obj = joinPoint.getArgs();

        for (Object eve : obj) {
            //车辆列表操作
            if (eve instanceof CarInfo) {
                adminLog.setCarinfoId(((CarInfo) eve).getCarinfoId());
                adminLog.setCarName(((CarInfo) eve).getCarName());
                adminLog.setColor(((CarInfo) eve).getColor());
                adminLog.setCarNumber(((CarInfo) eve).getCarNumber());
                adminLogs.add(adminLog);
            }
            //用车信息列表操作
            if (eve instanceof CarUseInfo) {
                CarInfoAndUser carInfoAndUser = carInfoMapper.selectCarInfoByCarinfoId(((CarUseInfo) eve).getCarinfoId());
                adminLog.setUseinfoId(((CarUseInfo) eve).getUseinfoId());
                adminLog.setCarinfoId(((CarUseInfo) eve).getCarinfoId());
                adminLog.setCarName(carInfoAndUser.getCarName());
                adminLog.setColor(carInfoAndUser.getColor());
                adminLog.setCarNumber(carInfoAndUser.getCarNumber());
                adminLogs.add(adminLog);
            }
            //针对删除操作
            if (eve instanceof String) {
                String[] split = ((String) eve).split(",");
                for (String item : split) {
                    AdminLog batchdel = new AdminLog();
                    Long id = Long.parseLong(item);
                    CarInfoAndUser carInfoAndUser = carInfoMapper.selectCarInfoByCarinfoId(id);
                    batchdel.setCarinfoId(id);
                    batchdel.setCarName(carInfoAndUser.getCarName());
                    batchdel.setColor(carInfoAndUser.getColor());
                    batchdel.setCarNumber(carInfoAndUser.getCarNumber());
                    adminLogs.add(batchdel);

                    //获取操作--方法上的Log的值
                    MyLog myLog = method.getAnnotation(MyLog.class);
                    if (myLog != null) {
                        //保存操作事件
                        String operation = myLog.operation();
                        batchdel.setOperationName(operation);
                    }

                    // 操作人账号、姓名(需要提前将用户信息存到session)
                    SysUser sysUser = (SysUser) SecurityUtils.getSubject().getPrincipal();
                    if (sysUser != null) {
                        Long userId = sysUser.getUserId();
                        String userName = sysUser.getUserName();
                        batchdel.setOperationBy(userId);
                        batchdel.setUserName(userName);
                    }

                    //存入操作时间
                    Date date = new Date();
                    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String format = simpleDateFormat.format(date);
                    batchdel.setOperationTime(format);
                }
            }
        }

        //获取操作--方法上的Log的值
        MyLog myLog = method.getAnnotation(MyLog.class);
        if (myLog != null) {
            //保存操作事件
            String operation = myLog.operation();
            adminLog.setOperationName(operation);
        }

        // 操作人账号、姓名(需要提前将用户信息存到session)
        SysUser sysUser = (SysUser) SecurityUtils.getSubject().getPrincipal();
        if (sysUser != null) {
            Long userId = sysUser.getUserId();
            String userName = sysUser.getUserName();
            adminLog.setOperationBy(userId);
            adminLog.setUserName(userName);
        }

        //存入操作时间
        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(date);
        adminLog.setOperationTime(format);

        //调用service保存Operation实体类到数据库
        carUseRecordService.insertCarUseRecord(adminLogs);
    }
}

controller

/**
     * 新增保存车辆信息
     */
    @MyLog(operation = "新增车辆")
    @RequiresPermissions("system:carInfo:add")
    @Log(title = "车辆信息", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(CarInfo carInfo)
    {
        return toAjax(carInfoService.insertCarInfo(carInfo));
    }


    /**
     * 修改保存车辆信息
     */
    @MyLog(operation = "修改车辆")
    @RequiresPermissions("system:carInfo:edit")
    @Log(title = "车辆信息", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(CarInfo carInfo)
    {
        return toAjax(carInfoService.updateCarInfo(carInfo));
    }

在controller的方法上加上我们的自定义注解,并写上相应的操作名称

然后切面类中


@Pointcut("@annotation(com.ruoyi.car.aop.MyLog)")


只要访问添加MyLog注解的方法都会被AOP给拦截,然后我们可以获得方法中的传参,将信息存入数据库中。

流!