• SpringAOP + 注解实现日志管理


    SpringAOP + 注解实现日志管理

    1. 什么是AOP?

    AOP(Aspect Orient Programming),翻译过来就是面向切面编程,面向对象编程是将程序抽象成多个层次的对象,面向切面是将程序抽象成多个切面

    2. 为什么要使用AOP(场景说明)

    在时间开发中,我们有很多模块中会使用到重复的代码,我们肯定不会通过复制的形式来复用代码.当然解决方式也是多种的,通常我们会将重复的代码抽离出来,提取成一个方法或者是一个抽象的类.然后在需要调用的地方,调用这个方法即可.但是随着我们的业务改变,加入改方法被删除不需要使用,我们需要对所有调用的地方进行单独的删除,这就增加了工作的难度,此时便有了AOP.AOP的原理是代理模式

    3. 实际案例

    使用AOP的方式,完成日志管理

    1. 日志管理数据结构

    CREATE TABLE `sys_log` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `operation` varchar(50) DEFAULT NULL COMMENT '操作',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      `method_name` varchar(100) DEFAULT NULL COMMENT '方法名',
      `param_name` varchar(500) DEFAULT NULL COMMENT '参数',
      `ip` varchar(100) DEFAULT NULL COMMENT 'ip地址',
      `username` varchar(50) DEFAULT NULL COMMENT '用户名',
      PRIMARY KEY (`id`),
      UNIQUE KEY `id` (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8
    复制代码

    日志表对应的实体类,mapper,service,controller 可以通过mybatisplus自动生成,这里就省略不写了.

    2. 日志管理切入面(代码加强)

    /**
     * @ClassName LoginLogAspect
     * @Description  操作日志切入面
     * @Author xiongchao
     * @Date 2020/9/27 10:22
     **/
    @Aspect
    @Component
    public class SysLogAspect {
    
        @Autowired
        private ISysLogService logService;
    
        @Autowired
        private ApplicationProperties properties;
    
        @Autowired
        private JwtTokenUtil util;
    
        //定义切点 @Pointcut
        //在注解的位置切入代码
        @Pointcut("@annotation( com.adingxiong.cft.aop.Mylog)")
        public void logPoinCut() {
    
        }
    
        //切面 配置通知
        @AfterReturning("logPoinCut()")
        public void savaLog(JoinPoint joinpoin){
    
            SysLog sysLog = new SysLog();
    
            //从切面织入点处通过反射机制获取织入点处的方法
            MethodSignature signature = (MethodSignature) joinpoin.getSignature();
            //获取切入点所在的方法
            Method method = signature.getMethod();
            Mylog myLog = method.getAnnotation(Mylog.class);
    
            if(myLog != null){
                String value  = myLog.value();
                sysLog.setOperation(value);
            }
    
            //获取请求的类名
            String className = joinpoin.getTarget().getClass().getName();
    
            //获取请求的方法名
            String methodName = method.getName();
            sysLog.setMethodName(className + "." + methodName);
    
            HttpServletRequest request=((ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes()).getRequest();
    
            String token  = request.getHeader(properties.getTokenHeader());
    
            String authToken = token.substring(properties.getTokenHead().length());
            String username = util.getUserNameFromToken(authToken);
    
            sysLog.setUsername(username);
    
            String ip = IpUtils.getRealIp(request);
            sysLog.setIp(ip);
    
            //请求参数
            Object args [] = joinpoin.getArgs();
            String param = JSON.toJSONString(args);
            sysLog.setParamName(param);
            sysLog.setCreateTime(new Date());
            logService.save(sysLog);
        }
    
    }
    
    复制代码

    3. 获取IP的工具类

    /**
     * @ClassName IpUtils
     * @Description  获取用户的真实ip
     * @Author xiongchao
     * @Date 2020/9/27 10:08
     **/
    public class IpUtils {
    
        public static String getRealIp(HttpServletRequest request) {
            String ipAddress = request.getHeader("x-forwarded-for");
            if(ipAddress == null || ipAddress.length() ==0 || "unknown".equals(ipAddress)){
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (StringUtils.isEmpty(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_CLIENT_IP");
            }
            if (StringUtils.isEmpty(ipAddress) || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
            }
            if(ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
                if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
                    //根据网卡取本机配置的IP
                    InetAddress inet=null;
                    try {
                        inet = InetAddress.getLocalHost();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ipAddress= inet.getHostAddress();
                }
            }
            //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
            if(ipAddress!=null && ipAddress.length()>15){ //"***.***.***.***".length() = 15
                if(ipAddress.indexOf(",")>0){
                    ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
                }
            }
            return ipAddress;
        }
    
    }
    
    复制代码

    4. 自定义注解(通过注解的方式调用切面方法)

    /**
     * @ClassName Mylog
     * @Description TODO
     * @Author xiongchao
     * @Date 2020/9/27 10:29
     **/
    @Target(ElementType.METHOD) //注解放置的目标位置,METHOD是可注解在方法级别上
    @Retention(RetentionPolicy.RUNTIME) //注解在哪个阶段执行
    @Documented //生成文档
    public @interface Mylog {
        String value() default "";
    }
    复制代码

    5. 测试

    Service层或者controller层添加@MyLog(value="xxxxx")注解完成调用

        @Mylog(value = "获取当前用户信息")
        @ApiOperation(value = "获取当前登录用户信息")
        @GetMapping("/info")
        public Result<Map<String,Object>> getUserInfo(Principal principal){
            if(principal == null){
                return Result.unauthorized(null);
            }
            String username = principal.getName();
            TUser user = userService.getUserByUsername(username);
            List<Role> list = roleService.getUserRole(user.getId());
            Map<String,Object> res = new HashMap<>();
            res.put("userInfo",user);
            res.put("role",list);
            return Result.success(res);
        }
    
    复制代码

    本文使用 mdnice 排版

    来源:https://juejin.cn/post/6881812630789423117
  • 相关阅读:
    基于UML的科研管理系统 的设计与实现06
    基于UML的科研管理系统 的设计与实现05
    基于UML的科研管理系统 的设计与实现04
    基于UML的科研管理系统 的设计与实现03
    《暗时间》读后感
    毕业设计之文献综述目录
    基于UML的科研管理系统 的设计与实现02
    基于UML的科研项目管理系统的设计与实现01
    【手撕】中序遍历二叉树
    【手撕】二叉树前序遍历
  • 原文地址:https://www.cnblogs.com/konglxblog/p/16725116.html
Copyright © 2020-2023  润新知