写点什么

Springboot 如何使用 Aspect 来实现切面日志

  • 2021 年 12 月 23 日
  • 本文字数:2710 字

    阅读完需:约 9 分钟

以系统日志为例

首先,我们先做一些准备工作。

1、新建一个 Springboot 工程

2、添加必要的依赖

AOP 必须

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId></dependency>
复制代码

gson 主要是我用于数据的处理,不是必须的

<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.1</version></dependency>
复制代码


个人喜好

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope></dependency><dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional></dependency>
复制代码

3、日志实体类和 service

package com.space.aspect.bo; import lombok.Data; /** * 系统日志bo * @author zhuzhe */@Datapublic class SysLogBO {     private String className;     private String methodName;     private String params;     private Long exeuTime;     private String remark;     private String createDate;}
复制代码


package com.space.aspect.service; import com.space.aspect.bo.SysLogBO;import lombok.extern.slf4j.Slf4j;import org.springframework.stereotype.Service; /** * @author zhuzhe */@Slf4j@Servicepublic class SysLogService {     public boolean save(SysLogBO sysLogBO){        // 这里就不做具体实现了        log.info(sysLogBO.getParams());        return true;    }}
复制代码


4、定义日志注解

这里呢,我们记录日志使用注解的形式。所以,先定义一个注解

package com.space.aspect.anno; import java.lang.annotation.*; /** * 定义系统日志注解 * @author zhuzhe */@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface SysLog {    String value() default "";}
复制代码


5、声明切面,完成日志记录

以上 4 点我们的准备工作已经完成。接java培训下来就是重点了

这里需要你对 AOP 有一定的了解。起码知道切点表达式、环绕通知、前置通知、后置通知等。。。

package com.space.aspect.aspect; import com.google.gson.Gson;import com.space.aspect.anno.SysLog;import com.space.aspect.bo.SysLogBO;import com.space.aspect.service.SysLogService;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.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component; import java.lang.reflect.Method;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List; /** * 系统日志切面 * @author zhuzhe */@Aspect  // 使用@Aspect注解声明一个切面@Componentpublic class SysLogAspect {     @Autowired    private SysLogService sysLogService;     /**     * 这里我们使用注解的形式     * 当然,我们也可以通过切点表达式直接指定需要拦截的package,需要拦截的class 以及 method     * 切点表达式:   execution(...)     */    @Pointcut("@annotation(com.space.aspect.anno.SysLog)")    public void logPointCut() {}     /**     * 环绕通知 @Around  , 当然也可以使用 @Before (前置通知)  @After (后置通知)     * @param point     * @return     * @throws Throwable     */    @Around("logPointCut()")    public Object around(ProceedingJoinPoint point) throws Throwable {        long beginTime = System.currentTimeMillis();        Object result = point.proceed();        long time = System.currentTimeMillis() - beginTime;        try {            saveLog(point, time);        } catch (Exception e) {        }        return result;    }     /**     * 保存日志     * @param joinPoint     * @param time     */    private void saveLog(ProceedingJoinPoint joinPoint, long time) {        MethodSignature signature = (MethodSignature) joinPoint.getSignature();        Method method = signature.getMethod();        SysLogBO sysLogBO = new SysLogBO();        sysLogBO.setExeuTime(time);        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");        sysLogBO.setCreateDate(dateFormat.format(new Date()));        SysLog sysLog = method.getAnnotation(SysLog.class);        if(sysLog != null){            //注解上的描述            sysLogBO.setRemark(sysLog.value());        }        //请求的 类名、方法名        String className = joinPoint.getTarget().getClass().getName();        String methodName = signature.getName();        sysLogBO.setClassName(className);        sysLogBO.setMethodName(methodName);        //请求的参数        Object[] args = joinPoint.getArgs();        try{            List<String> list = new ArrayList<String>();            for (Object o : args) {                list.add(new Gson().toJson(o));            }            sysLogBO.setParams(list.toString());        }catch (Exception e){ }        sysLogService.save(sysLogBO);    }}
复制代码


6、测试

接下来,我们就来测试一下吧

package com.space.aspect.controller; import com.space.aspect.anno.SysLog;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController; /** * @author zhuzhe */@RestControllerpublic class TestController {     @SysLog("测试")    @GetMapping("/test")    public String test(@RequestParam("name") String name){        return name;    }}
复制代码

启动项目,访问我们的 test 方法。

我们在 service 里打一个断点



可以看到,我们所需要的值都成功拿到了。

这样,我们就成功实现了使用 Aspect 实现切面记录日志。

转自 Java 笔记虾

用户头像

关注尚硅谷,轻松学IT 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
Springboot如何使用Aspect来实现切面日志