• 使用aop切面编写日志模块


    我们先自定义一个注解(一个有关自定义注解的LJ文章 https://www.cnblogs.com/guomie/p/10824973.html

    /**
    *
    * 自定义日志注解
    * Retention(RetentionPolicy.RUNTIME) 生命周期永远不会被丢弃
    * Target(ElementType.METHOD) 作用于方法上
    * Documented
    */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface LogAnnotation {
    
       // 描述
       String actiondese() default "";
    
       //类型
       public enum Logtype {ADD,UPDATE,DEL,SET,LOGIN,LOGOUT,MESSAGE};
    
       Logtype actionvalue() default Logtype.ADD;
    }

    我们编写一个切面类

    @Aspect
    @Component
    public class LogAop {
    @Autowired
    private RedisService redisService;

    @Autowired
    private LogService logService;

    // 切点
    // @Pointcut("execution(* com.monitoring.controller..*.*(..))")
    @Pointcut("@annotation(com.annotations.LogAnnotation)")
    private void controllerAspect() {}

    //增强
    @Around("controllerAspect()")
    public Object log(ProceedingJoinPoint pjp )throws Throwable{

        //先运行目标方法
    Object object = pjp.proceed();

    //获取request
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
    HttpServletRequest request = servletRequestAttributes.getRequest();

    // 拦截当前方法的对象
    Object target = pjp.getTarget();
    // 获取正在拦截方法名称
    String methodName = pjp.getSignature().getName();
    // 获取方法的参数
    Object[] args = pjp.getArgs();
    // 获取请求的路径
    // String requestURI = request.getRequestURI();

    // 拦截的放参数类型
    Signature sig = pjp.getSignature();
    MethodSignature msig = null;
    if (!(sig instanceof MethodSignature)) {
    throw new IllegalArgumentException("该注解只能用于方法");
    }
    msig = (MethodSignature) sig;
    Class[] parameterTypes = msig.getMethod().getParameterTypes();

    Method method = null;
    String actionType = "07";
    String actionDesc = "";
    try {

    // 获取当前方法
    method = target.getClass().getMethod(methodName, parameterTypes);

    } catch (NoSuchMethodException | SecurityException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
    }


    if (null != method) {

    // 获取方法上的注解
    LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
    if(null == annotation) {
    return object;
    }
    // 获取注解上的信息
    actionDesc = annotation.actiondese();
    // 获取类型
    Logtype actionvalue = annotation.actionvalue();

    switch (actionvalue) {
    case ADD:
    actionType = "00";
    break;
    case UPDATE:
    actionType = "01";
    break;
    case DEL:
    actionType = "02";
    break;
    case SET:
    actionType = "03";
    break;
    case LOGIN:
    actionType = "04";
    break;
    case LOGOUT:
    actionType = "05";
    break;
    case MESSAGE:
    actionType = "06";
    break;
    default:
    actionType = "07";
    break;
    }
    }

    // 获取访问真实IP
    String internetIp = request.getHeader("x-forwarded-for");
    if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
    internetIp = request.getHeader("Proxy-Client-IP");
    }
    if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
    internetIp = request.getHeader("WL-Proxy-Client-IP");
    }
    if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
    internetIp = request.getRemoteAddr();
    if (internetIp.equals("127.0.0.1") || internetIp.equals("0:0:0:0:0:0:0:1")) {
    // 根据网卡取本机配置的IP
    InetAddress inet = null;
    try {
    inet = InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
    e.printStackTrace();
    }
    internetIp = inet.getHostAddress();
    }

    }
    //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
    if (internetIp != null && internetIp.length() > 15) { // "***.***.***.***".length() = 15
    if (internetIp.indexOf(",") > 0) {
    internetIp = internetIp.substring(0, internetIp.indexOf(","));
    }
    }

    // 创建日志对象用于保存
    BsUserLog4j log = new BsUserLog4j();
    BsUserInfo user = JsonUtils.jsonToPojo(redisService.get(args[0].toString()), BsUserInfo.class) ;

    //用户登出
    if(actionType == "04") {
    //删除缓存中的token值
    redisService.del(args[0].toString());
    System.out.println("已删除缓存中token值");
    }
    //设置时间
    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String actionTime=sdf.format(new Date());

    // 设置log信息并保存数据库
    log.setLogId(new BigDecimal(IDUtils.genId()));
    log.setUsername(user.getUsername());
    log.setActionType(actionType);
    log.setActionTime(actionTime);
    log.setActionDesc(actionDesc);
    log.setInternetIp(internetIp);

    //添加日志到数据库
    logService.addLog(log);
    System.out.println("添加日志: " + log.toString());

    //最后返回目标方法
    return object;
    }
    }

    在配置里里面配置有关aop的配置

    <beans   xmlns:aop="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" <beans>
    
    <!-- 自动为@aspectJ切面bean创建代理,true表示使用CGLib来创建 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />

    controller层代码

    @LogAnnotation(actiondese="用户登录",actionvalue=Logtype.LOGIN)
    @RequestMapping("/loginTest")
    @ResponseBody
    public CarResult loginTest(HttpServletResponse response,HttpServletRequest request, String name,String pas,String phoneNumer){}

     其中还会遇到一些问题 

    1. error at ::0 formal unbound in pointcut 

    当出现这个错误的时候 表示你的通知方法得带上参数 比如

    但是 request 不能通过参数传递进来 只能通过下面方式来获取

    RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes servletRequestAttributes =  (ServletRequestAttributes) requestAttributes;
    HttpServletRequest request = servletRequestAttributes.getRequest();

    2.目标方法不执行

      这时候我们需要先执行目标方法,然后再讲目标方法通过返回值返回出去

    关注公众号,回复:java面试题,即可获得共几百页的java面试题

  • 相关阅读:
    Linux学习笔记(二):实战-根据微服务端口号关闭进程
    Linux学习笔记(一):文件操作命令
    算法-Java组合
    Springboot学习笔记(六)-配置化注入
    Springboot学习笔记(五)-条件化注入
    Springboot学习笔记(四)-配置相关
    Springboot学习笔记(三)-常用注入组件方式
    CentOS7安装MySQL
    扫二维码下载apk并统计被扫描次数(及微信屏蔽下载解决方案)
    Java jacob调用打印机打印word文档
  • 原文地址:https://www.cnblogs.com/guomie/p/10765345.html
Copyright © 2020-2023  润新知