我的aop记录日志,可以记录:【 操作类型、操作描述、参数、登录项目的用户ip】 当然记录什么靠你自己决定。

一.自定义一个注解

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

    //操作描述
    String description() default "";

    //操作类型
    String operateType() default "";
    
}

二.定义aop记录日志工具类

  • @Before: 前置通知, 在方法执行之前执行。
  • @After: 后置通知, 在方法执行之后执行 。
  • @AfterRunning: 返回通知, 在方法返回结果之后执行。
  • @AfterThrowing: 异常通知, 在方法抛出异常之后。
  • @Around: 环绕通知, 围绕着方法执行、
@Aspect
@Component
public class LogAspectUtil  {

	//这是我自己的接口实现类,就是存入我的数据库需要的接口
    @Autowired
    private PsLogServiceImpl psLogService; 

    /**
     * service层切点
     */
    @Pointcut("@annotation(com.navi.vpx.common.util.AopLog)") //这里是你自定义注解的位置
    public void serviceAspect() {
    }

    /**
     * 记录日志,写入数据库
     * @param joinPoint 切入点参数
     */
    @After("serviceAspect()")//这里设置的是当你的方法执行完之后,才会执行该方法,也可以使用上面不同的注解在不同时间进行记录。
    public void doServiceLog(JoinPoint joinPoint) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        
        //这里是获取登录你项目用户的ip地址
        try { 
            String unknown = "unknown";
//            String ip0 = request.getHeader("x-forwarded-for");
            String ip = request.getHeader("X-Real-IP");

            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }

            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }

            if (ip == null || ip.length() == 0 || unknown.equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
            }

//            if (LOCAL_IP.equals(ip)) {
//                ip = "local";
//            }

			//将记录写入数据库
            PsLog psLog = new PsLog();
            psLog.setCreateTime(new Date());//设置当前时间
            psLog.setDes( "操作描述:" + getDes(joinPoint) + "   操作类型:" + getOperateType(joinPoint) );//操作描述和操作类型
            psLog.setArgs(getArgs(joinPoint));//设置参数
            psLog.setIp(ip);//设置当前登录用户ip
            psLogService.insertLog(psLog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取方法的描述信息
     * @param joinPoint
     * @return
     */
    private String getDes(JoinPoint joinPoint) throws ClassNotFoundException {
        //获取被代理对象名称
        String targetName = joinPoint.getTarget().getClass().getName();
        //获取目标方法名称
        String methodName = joinPoint.getSignature().getName();
        //获取传入目标方法的参数对象
        Object[] arguments = joinPoint.getArgs();
        //获取class对象
        Class targetClass = Class.forName(targetName);
        //获取对象中的所有方法
        Method[] methods = targetClass.getMethods();
        String des = "";
        //下面是进行匹配,方法名和目标方法名相同,且参数相同,则获取注解内的相应参数,用来进行日志记录
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    des = method.getAnnotation(ConfigAopLogService.class).description();
                    break;
                }
            }
        }
        return des;
    }

    /**
     * 获取操作表的操作类型
     * @param joinPoint
     * @return
     */
    private String getOperateType(JoinPoint joinPoint) throws ClassNotFoundException {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String operateType = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                if (method.getParameterTypes().length == args.length) {
                    operateType = method.getAnnotation(ConfigAopLogService.class).operateType();
                    break;
                }
            }
        }
        return operateType;
    }


    /**
     * 获取操作表的参数(你的参数是对象,会查出属性名及其值)
     * @param joinPoint
     * @return
     */
    private String getArgs(JoinPoint joinPoint) throws ClassNotFoundException {
        int index = -1; //记录下标
        String arg = "";//拼接参数
        Object[] args = joinPoint.getArgs();
        Signature signature = joinPoint.getSignature();//此处joinPoint的实现类是
        MethodSignature methodSignature = (MethodSignature) signature;//获取参数名
        for(int i=0;i<methodSignature.getParameterNames().length;i++){
            if (methodSignature.getParameterNames()[i].equals("request")){//获取参数名字为request的参数
                index = i;
            }
        }

        for (int j = 0; j<args.length; j++) {//循环参数对象
            if (index != -1 && index == j){ //不拼接request参数
                break;
            }
            Class<?> aClass = args[j].getClass();
            Field[] fields = aClass.getDeclaredFields();// 根据Class对象获得属性 私有的也可以获得
            try {
                for (Field f : fields) {
                    f.setAccessible(true); // 设置些属性是可以访问的
                    Object val = f.get(args[j]); // 得到此属性的值
                    String name = f.getName(); // 得到此属性的名称
                    arg += name + ":" + val + ", ";
                }
            } catch (IllegalAccessException e) {
                System.out.println("报错");
            }
        }
        System.out.println(arg);
        return arg;
    }
}

三.实际操作和数据库的值

1.把注解放在某个方法上

android aop记录日志 aop日志记录_spring

2.然后请求该方法,你的数据库就会存入对应的日志

操作描述操作类型 没办法自动获取所以我们手打就可以,而参数当前用户ip可以自动获取到,所以我们之间存入我们的实体类里面,然后直接存入数据库。

android aop记录日志 aop日志记录_android aop记录日志_02

四.以上还需要你自己建立你想要的数据库表和交互数据库的接口

觉得还不错,点个赞吧,栓Q!