Spring boot AOP + 自定义注解实现用户请求日志记录(文件)

自定义注解

/**
 * @ClassName RouteLog
 * @Description 路由日志记录自定义注解
 * @Author 何小树
 * @Date 2019/11/7 15:10
 **/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface RouteLogAnnotation {

    //是否保存日志文件
    boolean saveLog() default false;

}

AOP

依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

日志实体类

@Getter
@Setter
public class RouteLog {
    private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final RouteLog routelog = new RouteLog();
    private RouteLog() {}
    public static RouteLog getInstance(){return routelog;}

    private String uuid;
    private String routeUrl;
    private Long startTime;
    private String ip;
    private String parameter;

    @Override
    public String toString() {
        return " 请求路径:"+this.routeUrl+" 请求ip:"+this.ip+
               " 请求时间:"+ simpleDateFormat.format(new Date(this.startTime)) +
               " 请求参数:"+ this.parameter ;
    }

}

AOP实现

@Aspect
@Component
public class RouteLogAspect {

    private RouteLog routeLog = RouteLog.getInstance();

    @Pointcut("@annotation(com.annotation.RouteLogAnnotation)")
    public void routeLog(){}

    @Before(value = "routeLog()")
    public Object doBefore(JoinPoint joinPoint){
        Object res=null;
        long time = System.currentTimeMillis();
        try {
            insertRouteLog(joinPoint);
            time=System.currentTimeMillis()-time;
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }finally {
            System.out.println("执行结束");
        }
        return null;
    }

    private void insertRouteLog(JoinPoint joinPoint){
        long startTime=System.currentTimeMillis();
        PrintStream ps =null;
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        MethodSignature signature = (MethodSignature)joinPoint.getSignature();
        Object[] args = joinPoint.getArgs();//访问目标方法的参数 可动态改变参数值
        RouteLogAnnotation annotation = signature.getMethod().getAnnotation(RouteLogAnnotation.class);
        if (annotation!=null){
            boolean saveLog = annotation.saveLog();//是否开启存储文件日志记录
            String ip = StringUtil.getRemoteHost(request);
            String uri = request.getRequestURI();
            routeLog.setStartTime(startTime);
            routeLog.setIp(ip);
            routeLog.setUuid(StringUtil.getUUID());
            routeLog.setRouteUrl(uri);
            routeLog.setParameter(Arrays.toString(args));
            System.out.println("日志记录:"+routeLog.toString());
            try {
                //如果开始存储请求路由日记记录
                if (saveLog){
                    String now = DateUtil.NowDateYmd();
                    String routePath = FileUtil.getJarPath("routeLog")+now+".txt";
                    Path path = Paths.get(routePath);
                    if (!Files.exists(path)){
                        File file = new File(routePath);
                        boolean newFile = file.createNewFile();
                        System.out.println("日志存储路径:"+routePath);
                        if (newFile) System.out.println("日志文件创建成功");
                    }else {
                        FileOutputStream fo = new FileOutputStream(routePath,true);
                        ps = new PrintStream(fo);
                        System.setOut(ps);
                        System.out.println(routeLog.toString());
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(ps!=null)ps.close();
            }
        }

    }

    @AfterReturning(returning = "result", pointcut = "routeLog()")
    public void doAfterReturning(Object result){
        System.out.println("Result:"+result.toString());
    }


}

路径方法

/**
     * 项目jar 部署时,获取jar同级目录,用于图片存储等
     * @param subdirectory
     * @return
     */
    public static String  getJarPath(String subdirectory){
        //获取跟目录---与jar包同级目录的upload目录下指定的子目录subdirectory
        File upload = null;
        try {
            //本地测试时获取到的是"工程目录/target/upload/subdirectory
            File path = new File(ResourceUtils.getURL("classpath:").getPath());
            if(!path.exists()) path = new File("");
            upload = new File(path.getAbsolutePath(),subdirectory);
            if(!upload.exists()) upload.mkdirs();//如果不存在则创建目录
            return upload + File.separator;
        } catch (FileNotFoundException e) {
            throw new RuntimeException("获取服务器路径发生错误!");
        }
    }

这只是个基础实现,切入点是自定义注解;就实现了 请求方法上有注解的才会进入日志记录。
这里是,实现存储存日志文件 ,也可以存储数据库,可以做很多扩展。

普通访问日志切面:

import cn.czc.kingdee.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * @program: zyd
 * @description:  访问日志切面
 * @author: he
 * @create: 2020-08-24 16:50
 **/
@Slf4j
@Aspect
@Component
public class RouteLogAspect {

    @Pointcut("execution(* cn.czc.kingdee.controller..*(..))")
    public void routeLog(){}

    @Before(value = "routeLog()")
    public Object before(JoinPoint joinPoint){
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        Object[] args = joinPoint.getArgs();
        String ip = StringUtil.getIp(request);
        String uri = request.getRequestURI();
        log.info("访问ip:{} , api:{} ,请求参数: {}",ip,uri,args);
        return null;
    }

    @AfterReturning(returning = "result", pointcut = "routeLog()")
    public void doAfterReturning(Object result){
        log.info("返回数据:{}",result.toString());
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值