一、简要说明

     如今SpringBoot技术快速发展,采用注解开发更是现在开发的热潮。博主自己就结合自己在项目中关于日志功能的实现,采用AOP来拦截前端请求,获取我们所需的信息来实现日志功能。我会从搭建项目到能自己根据需求获得自己想要的数据,一步一步,让大家明白如何实现日志管理功能的。由于博主个人 能力有限,对 文章的描述就采用大白话,如果有描述不清楚的地方,希望各位大佬指正!

二、关于AOP的介绍

      一谈到aop大家可能就会想到Spring,因为Spring具有两大特征IOC与AOP,而AOP又是里面的核心。一说AOP条件反射随口而出"切面编程",说定义大家都懂,但如何利用AOP我相信大多数人还是一头雾水。不过不用担心,我相信通过我接下来的介绍,会让大家重新有一个对AOP不一样的认识。

三、项目搭建

     以下内容是关于如何创建一个SpringBoot的项目的步骤,会的小伙伴,自动跳过即可。

    ①:

②:③:四、准备工作

1、导入依赖

mysql

mysql-connector-java

runtime

org.springframework.boot

spring-boot-starter-aop

com.baomidou

mybatis-plus-boot-starter

3.3.2

org.projectlombok

lombok

true

2、创建数据库表

关于mylog表中的字段根据自己的需求设定了,我就设置几个比较常用的,后面我会介绍还可以请求到 那些数据

四、后台代码的书写

这里博主先将基础的MVC架构的代码写出来,再写关于自定义注解的方法

1、pojo层

@Data

@TableName("mylog")

public class Mylog {

@TableId(type = IdType.AUTO)

private Integer operationId;

private String operationModel;

private String operationDescribe;

private String requestMethod;

private String requestParam;

private String operationUrl;

}

2、DAO层

@Mapper

public interface MylogDao extends BaseMapper {

}

3、Service层

public interface MylogService {

int SaveLog(Mylog mylog);

}

@Service

public class MylogServiceImp implements MylogService {

@Resource

private MylogDao mylogDao;

@Override

public int SaveLog(Mylog mylog) {

return mylogDao.insert(mylog);

}

}

4、controller层

   当我们写完所有代码时,在测试的时候,就是调用的controller层下的方法,看aop是否拦截我们所需的数据。

@Controller

public class MyLogController {

@Log(operationModel = "登录模块" , operationDescribe = "访问登录模块")

@GetMapping("/login/{name}/{age}")

@ResponseBody

public String Login(@PathVariable("name") String name, @PathVariable("age") Integer age){

return name+"今年"+age+"岁登录了系统";

}

}

5、自定义注解(重点)

从这里开始就是我们需要学习的重点部分了,首先我们像普通注解一样定义一个自己用于切面的注解,代码如下:

@Documented

@Target({ElementType.METHOD})//表示放在controller层的方法上

@Retention(RetentionPolicy.RUNTIME)//表示注解在那个阶段执行

public @interface Log {

//写在注解里面,可以用于存到数据库时的对方法的描述

String operationModel() default " ";//操作模块

String operationDescribe() default " ";//操作说明

}

6、定义切面(重点)

如果只有自定义的注解,没有定义切面和切点,AOP是没有起到拦截的作用,先呈上代码再做详细 解释。

@Component// 让SpringBoot来识别到

@Aspect//切面 定义了 通知与切点的关系

public class LogAspect {

private Mylog mylog;

@Resource

private MylogService mylogService;

@Pointcut("@annotation(com.ghs.test.annotation.Log)")//定义切点 表示注解加在哪里(添加全路径)

public void PointCut(){

}

@Before("PointCut()")

public void Before(JoinPoint joinPoint){

mylog = new Mylog();

ServletRequestAttributes requests = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();

HttpServletRequest request = requests.getRequest();

//通过HttpServletRequest对象request获取method、url;

mylog.setOperationUrl(request.getRequestURI());

mylog.setRequestMethod(request.getMethod());

mylog.setRequestParam(Arrays.toString(joinPoint.getArgs()));

//通过反射机制获得切入点处的方法

MethodSignature signature = (MethodSignature)joinPoint.getSignature();

Method method = signature.getMethod();

//获取在自定义的注解@Log()中的内容

Log annotation = method.getAnnotation(Log.class);

mylog.setOperationModel(annotation.operationModel());

mylog.setOperationDescribe(annotation.operationDescribe());

}

@Around("PointCut()")

public Object Around(ProceedingJoinPoint point) throws Throwable {

Object proceed = point.proceed();

mylogService.SaveLog(mylog);

System.out.println(mylog.toString());

return proceed;

}

}

上述代码中,除了有注释的地方,我会强调以下几个点:

①该代码理解

ServletRequestAttributes requests = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();

HttpServletRequest request = requests.getRequest();

如果你只是拿得到代码后就只是CV,那么对你个人能力的提升是大大打折扣的。现在让我来说明一下为什么可以拿到HttpServletRequest对象以及为什么要拿到它。

为什么可以拿到HttpServletRequest对象:

首先RequestContextHolder是Spring框架中的一个工具类,在该工具类中调用其静态方法法getRequestAttributes()获取当前线程中绑定的请求属性,然后将 RequestAttributes 对象转换为 ServletRequestAttributes 对象,最后,再通过servletRequestAttributes.getRequest()得到HttpServletRequest对象。

为什么要拿到HttpServletRequest对象呢:

HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息。

换句话说,当我们得到HttpServletRequest对象,我们可以从idea中看到有那些方法;

String getMethod();

String getPathInfo();

String getPathTranslated();

default PushBuilder newPushBuilder() {

return null;

}

String getContextPath();

String getQueryString();

String getRemoteUser();

boolean isUserInRole(String var1);

Principal getUserPrincipal();

String getRequestedSessionId();

String getRequestURI();

StringBuffer getRequestURL();

String getServletPath();

HttpSession getSession(boolean var1);

HttpSession getSession();

String changeSessionId();

boolean isRequestedSessionIdValid();

boolean isRequestedSessionIdFromCookie();

boolean isRequestedSessionIdFromURL();

以上等等方法都是HttpServletRequest自带的,我也是从中挑了几个比较常用的,所以我在前面说,你们可以根据自己的需求来设计需要的日志表哦。而且在我们真实的项目中需要获取session的时候,也可以通过该方法获得哦。

②该代码的理解

MethodSignature signature = (MethodSignature)joinPoint.getSignature();

Method method = signature.getMethod();

Log annotation = method.getAnnotation(Log.class);

Signature是 Java 反射 API 中的一个接口,在SpringAOP中可以通过 JoinPoint 对象获得连接点的相关信息,在该对象中通过getSignature() 方法获取到 Signature 对象,但因为我们的链接点是一个方法,可以将Signature 对象转换为 MethodSignature 对象,通过MethodSignature 对象可以获取到更加详细的方法签名信息。再通过反射获取自定义的注解,这样一来就可以得到我们自定义在@Log()里面的内容了。

③几个注解的理解

@Before("PointCut()")

表示在程序执行前执行。

@After("PointCut()")

表示在程序执行之后执行

@Around("PointCut()")

表示环绕整个程序执行

五、测试结果

我们访问MyLogController层下的"localhost:8080/login/567/18"接口,看是否能访问我们所需的信息。

效果展示

总上所述,我们成功将,需要拦截的方法描述、请求方法、请求参数、访问路径等信息在控制台输出并存到日志表中。

六、总结

     通过上面的描述我们就可以实现一个基本的采用SpringAOP实现的日志管理功能了,上面的代码虽小,但还是五脏俱全了,就算应付一些比较复杂的要求,明白了原理多查查相关资料也是能搞定的。如果,这篇文章对正在阅读的小伙伴来说有一定帮助的话,小伙伴不要忘记点赞多多支持博主哦。如果需要将我们的日志管理写在项目中,就记得在留言区留言,如果需要的小伙伴比较多,我后期就写一个HTML页面的,关于日志管理的模块(包含一些基本的操作的)。

好文推荐

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。