乐趣区

关于java:AOP面向切面编程-获取用户操作信息

切入点表达式:@Pointcut()括号内表达式的作用

package com.cy.pj.common.aspect;
@Slf4j
@Aspect
@Component
public class SysLogAspect {//@Pointcut 首先定义一个切点,bean(bean 对象的名字)为一种切入点表达式 (这个表达式定义了那个那些 bean 对象的办法要进行性能扩大)"bean(sysUserServiceImpl) 中的 sysUserServiceImpl 为交给 bean 创建对象的名"
//@Pointcut("bean(sysUserServiceImpl)")
// 这是写了一个注解, 以注解形式抉择要操作的办法
@Pointcut("@annotation(com.cy.pj.common.annotation.RequiredLog)")
    public void doLogPointCut() {}
//@Around 注解形容的办法为一个告诉办法(服务增益办法),jp 为连接点
@Around("doLogPointCut()")
    public Object doLogAround(ProceedingJoinPoint jp)throws Throwable {
        //1. 记录办法开始执行工夫
        try {long t1=System.currentTimeMillis();
            log.info("start:{}",t1);
            //2. 执行指标办法
            Object result=jp.proceed();// 最终 (两头还能够调用本类其它告诉或其它切面的告诉) 会调用指标办法
            //3. 记录办法完结执行工夫
            long t2=System.currentTimeMillis();
            log.info("after:{}",t2);
            //4. 将失常行为日志信息写入到数据库
             saveUserLog(jp,(t2-t1));
            //5. 返回指标办法执行后果
            return result;// 指标办法的返回后果
        }catch(Throwable e) {log.error("指标办法执行时呈现了异样:{}",e.getMessage());
            throw e;
        }
    @Autowired
    private SysLogService sysLogService;
/** 记录用户行为的失常信息 */
    private void saveUserLog(ProceedingJoinPoint jp,long time)throws Exception {
        //1. 获取用户行为日志
        String ip=IPUtils.getIpAddr();
        String username="cgb2005";// 未来是登录用户的用户名
        Date createdTime=new Date();
        // 获取操作名
        String operation=getOperation(jp);
        String method=getTargetClassMethod(jp);
        //String params=Arrays.toString(jp.getArgs());// 一般格局字符串
        String params=new ObjectMapper().writeValueAsString(jp.getArgs());//json 格局的参数
        //2. 封装用户行为日志(在内容中通过对象去实现)
        SysLog log=new SysLog();
        log.setIp(ip);
        log.setUsername(username);
        log.setCreatedTime(createdTime);
        log.setOperation(operation);
        log.setMethod(method);
        log.setParams(params);
        log.setTime(time);
        //3. 将用户行为日志长久化(将内存中对象信息写入到数据库)
        sysLogService.saveObject(log);
    }
    /** 获取指标办法的全限定名(指标类全名 + 办法名)*/
    private String getTargetClassMethod(ProceedingJoinPoint jp) {
        //1. 获取指标对象类型
        Class<?> targetCls=jp.getTarget().getClass();
        //2. 获取指标对象类型的类全名
        String targetClsName=targetCls.getName();
        //3. 获取指标办法名
        //3.1 获取办法签名(办法签名对象中封装了办法相干信息)
        MethodSignature ms=(MethodSignature)jp.getSignature();
        //3.2 基于办法签名获取办法名
        String methodName=ms.getName();
        //4. 构建办法的全限定名并返回
        return targetClsName+"."+methodName;
    }
/** 获取指标办法上 @ReqiredLog 注解中定义的 operation 名字    获取注解 value 的值 */
    private String getOperation(ProceedingJoinPoint jp)throws Exception {
        //1. 获取指标对象类型
        Class<?> targetCls=jp.getTarget().getClass();
        //2. 获取指标办法对象
        //2.1 获取办法签名信息
        MethodSignature ms=(MethodSignature)jp.getSignature();
        //2.2 获取办法对象
        // 如果心愿无论是 jdk 代理还是 cglib 代理, 咱们让 method 变量指向的都是指标对象中的办法对象, 那如何实现?
        Method method=targetCls.getDeclaredMethod(ms.getName(), ms.getParameterTypes());
        //3. 获取办法上的 reqiredLog 注解对象
        RequiredLog requiredLog=method.getAnnotation(RequiredLog.class);
        //4. 获取注解中的 operation 的值.
        if(requiredLog==null)return "operation";
        return requiredLog.operation();}
    }

获取 IP 地址的工具类


import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

public class IPUtils {private static Logger logger=LoggerFactory.getLogger(IPUtils.class);
    
public static String getIpAddr() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = null;
        try {ip = request.getHeader("x-forwarded-for");
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");
            }
        if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();
            }
        } catch (Exception e) {logger.error("IPUtils ERROR", e);
        }
        return ip;
    }

    }~~~~
退出移动版