前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringAOP + 注解实现日志管理

SpringAOP + 注解实现日志管理

作者头像
java攻城狮
发布2020-10-16 10:40:20
3920
发布2020-10-16 10:40:20
举报
文章被收录于专栏:个人积累个人积累

SpringAOP + 注解实现日志管理

1. 什么是AOP?

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

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

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

3. 实际案例

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

1. 日志管理数据结构
代码语言:javascript
复制
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. 日志管理切入面(代码加强)
代码语言:javascript
复制
/**
 * @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的工具类
代码语言:javascript
复制
/**
 * @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. 自定义注解(通过注解的方式调用切面方法)
代码语言:javascript
复制
/**
 * @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")注解完成调用

代码语言:javascript
复制
    @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 排版

Donate

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringAOP + 注解实现日志管理
    • 1. 什么是AOP?
      • 2. 为什么要使用AOP(场景说明)
        • 3. 实际案例
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档