栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【项目demo04】AOP日志管理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【项目demo04】AOP日志管理

我准备开一个系列,就是写一些在简要的学习项目中可能会用到的奇奇怪怪的功能,比如线程池或者统一异常处理类
取名为【项目demo】系列
然后将会同步到GitHub中:https://github.com/Livorth/FunctionalLearning


AOP日志管理

AOP是个好东西,用的地方很多,但是这里仅介绍作为日志管理的使用

总的来说,使用AOP的思路是差不多的

  1. 使用自定义注解
  2. 使用AOP环绕通知代理有对应注解的方法,然后在环绕的时候进行对应操作
  3. 在需要使用日志方法上加上注解,进行测试

在这里我并不会将日志信息入库,而是直接打印在控制台(因为入库麻烦但是容易实现)

我主要参考的 SpringBoot整合aop日志管理

使用自定义注解

注解一般相当于一个标记,一个传递信息的作用

LogAnnotation.java

package cn.livorth.functionallearning.common.log;

import java.lang.annotation.*;


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface LogAnnotation {
    // 操作模块
    String logModule() default "";
    // 操作类型
    String logType() default "";
    // 操作信息
    String logDescription() default "";
}
AOP环绕通知类

其实除了环绕@Around:,还可以选择@Before、@After、@AfterRunning、@AfterThrowing

比较推荐用@AfterThrowing,对异常进行特殊处理

在我的日志方法中,我并没有采用将日志记录进数据库,但是可以加上,比较容易写

package cn.livorth.functionallearning.common.log;



import cn.livorth.functionallearning.utils.HttpContextUtils;
import cn.livorth.functionallearning.utils.IpUtils;
import lombok.extern.slf4j.Slf4j;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;


@Aspect
@Component
@Slf4j
public class LogAspect {

    
    @Pointcut("@annotation(cn.livorth.functionallearning.common.log.LogAnnotation)")
    public void logPointCut(){}
    
    
    @Around("logPointCut()")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        long beginTime = System.currentTimeMillis();
        //执行方法
        Object result = joinPoint.proceed();
        //执行时长(毫秒)
        long time = System.currentTimeMillis() - beginTime;
        //保存日志
        recordLog(joinPoint, JSON.toJSONString(result), time);
        return result;
    }

    
    private void recordLog(ProceedingJoinPoint joinPoint, String result, long time) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);

        // 日志记录
        log.info("=====================log start================================");
        // 日志基础信息
        log.info("module:{}",logAnnotation.logModule());
        log.info("type:{}",logAnnotation.logType());
        log.info("description:{}",logAnnotation.logDescription());

        // 请求的方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        log.info("request method:{}",className + "." + methodName + "()");

        // 请求的参数
        Object[] args = joinPoint.getArgs();
        String params = JSON.toJSONString(args);
        log.info("params:{}",params);

        // 返回的结果
        log.info("result:{}",result);

        // 获取request 设置IP地址
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        log.info("ip:{}", IpUtils.getIpAddress(request));


        log.info("execution time : {} ms",time);
        log.info("=====================log end================================");

        // 这里可以将相关信息提取出来进行一个入库操作
    }
}
涉及到IP的处理

使用RequestContextHolder可以在Controller中获取request对象

然后可以使用request在请求头中找到对应的IP信息

这个部分是直接抄的,看起来大家都是通用的

HttpContextUtils.java

package cn.livorth.functionallearning.utils;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;


public class HttpContextUtils {

    // 在Controller中获取request对象
    public static HttpServletRequest getHttpServletRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
    }

}

IpUtils.java

package cn.livorth.functionallearning.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.http.HttpServletRequest;


@Slf4j
public class IpUtils {

    
    public static String getIpAddress(HttpServletRequest request) {
        String ip = null;
        String unknown = "unknown";
        String seperator = ",";
        int maxLength = 15;
        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) {
            log.error("IpUtils ERROR ", e);
        }

        // 使用代理,则获取第一个IP地址
        if (StringUtils.isEmpty(ip) && ip.length() > maxLength) {
            int idx = ip.indexOf(seperator);
            if (idx > 0) {
                ip = ip.substring(0, idx);
            }
        }
        return ip;
    }

    
    public static String getIpAddress() {
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        return getIpAddress(request);
    }
}
测试使用

分别在 getAllUser() 与 getAllUserByPage() 上加上 @LogAnnotation,并进行测试

@LogAnnotation(logModule = "user", logType = "select",  logDescription = "获取所有用户信息")
@GetMapping
public List getAllUser(){
    return userService.getAllUser();
}


@LogAnnotation(logModule = "user", logType = "select",  logDescription = "通过分页获取所有用户信息")
@GetMapping("page/{thePage}/{pageSize}")
public List getAllUserByPage(@PathVariable("thePage") int thePage, @PathVariable("pageSize") int pageSize){
    Page page = new Page<>(thePage, pageSize);
    return userService.getAllUserByPage(page);
}


写在后面

日志这种东西需要根据项目进行调整,毕竟很多的日志信息其实是无效信息,如果将这些东西存入数据库,只会占用服务器的资源,所以根据需求来,进行动态的调整才是最合适的


我的项目demo系列都会同步到GitHub上,欢迎围观

https://github.com/Livorth/FunctionalLearning

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/287097.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号