基于OpenAPI(Swagger3)使用AOP技术,进行日志记录

1.Swagger3和AOP结合的好处

当我们使用接口,或者问题定位,我们需要知道这么几个比较常见的信息:

  1. 这个接口干嘛用的?
  2. 这个接口的请求地址,请求方式,请求参数,返回参数都是什么样?
  3. 这个接口的代码在哪里?
  4. 当这个接口出现问题时,当时的运行的参数是什么?

如果你的项目中用了Swagger,你大概也能看到如下这种在线的接口文档,我们可以看到接口模块的描述,具体接口的功能描述,接口地址,接口的请求参数,返回参数等。
在这里插入图片描述
那么我们在记录日志的时候,如果把上述的Swagger中的这些参数都能记录下来,那么对于我们的工作来说,不管是定位问题,还是做日志审计,都非常有帮助。
例如下述的日志所示,这样做有什么好处?

  1. 我们可以不修改/添加任何日志记录代码就能记录我们我们的接口(controller)的访问日志;
  2. 我们可以将接口的日志用统一的方式管理起来,方便做日志审计;
    在这里插入图片描述

2.Swagger需要做什么

OpenAPI(Swagger3)首先需要对两处地方进行标记,一个是标记Controller类,一个是标记Controller的方法,即

使用@Api(tags = "")来标注这个类干嘛用的,
使用@ApiOperation(value = "")来标注这个方法干嘛用的

在这里插入图片描述

3.AOP需要做什么

  1. 找到我们需要进行切入的点,即我们需要切入的点是在Swagger中被@ApiOperation所修饰的方法
 @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
  1. 增强@ApiOperation所修饰的方法,也就是记录@ApiOperation方法的访问日志
 logger.info("请求{}模块的[{}]服务start",获取@Api的描述说明,获取ApiOperation的描述说明);
 logger.info("请求地址:{}",获取请求地址);
 logger.info("请求方法:{}.{}",获取@Api修饰的类名, 获取ApiOperatio修饰的方法名);
 logger.info("请求参数:{}",获取请求参数);
 result = joinPoint.proceed();
 logger.info("请求{}模块的{}服务end",获取@Api的描述说明,获取ApiOperation的描述说明);
 //将日志进行持久化,比如保存到数据库,代码略

4.完整代码示例

import javax.servlet.http.HttpServletRequest;

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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.cloud.simulation.utils.JsonUtils;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

/**
 * @description:基于swagger进行AOP日志记录
 * @author:hutao
 * @mail:hutao1@epri.sgcc.com.cn
 * @date:2022年10月17日 下午4:58:54
 */
@Aspect
@SpringBootConfiguration
public class LogApiConfig {
 
    private final Logger logger = LoggerFactory.getLogger(LogApiConfig.class);
	
    /**
     * @description:需要被切入的点是被@ApiOperation注解修饰的方法
     * @author:hutao
     * @mail:hutao1@epri.sgcc.com.cn
     * @date:2022年10月17日 下午4:59:20
     */
    @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
    public void pointcut() {
    	
    }
 
    /**
     * @description:进行日志切入
     * @author:hutao
     * @mail:hutao1@epri.sgcc.com.cn
     * @date:2022年10月17日 下午5:00:09
     */
    @Around("pointcut() && @annotation(apiOperation)")
    public Object around(ProceedingJoinPoint joinPoint, ApiOperation apiOperation) {
        Object result = null;
        try {
        	ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        	//获取请求地址
        	HttpServletRequest request = attributes.getRequest();
        	String url = request.getRequestURL().toString();
            //获取OpenAPI的类说明@Api
        	Class<?> controller = joinPoint.getThis().getClass();
            Api annotation = controller.getAnnotation(Api.class);
            String[] apiDes = annotation.tags();
            //获取被调用的方法名
            String methodName = joinPoint.getSignature().getName();
            //获取OpenAPI的方法说明@ApiOperation
			ApiOperation methodApiOperation = null;
			String apiOperationDes = "";
			MethodSignature ms = (MethodSignature) joinPoint.getSignature();
			methodApiOperation = ms.getMethod().getDeclaredAnnotation(ApiOperation.class);
			if (methodApiOperation != null) {
				apiOperationDes = methodApiOperation.value();
			}
            logger.info("请求{}模块的[{}]服务start",apiDes,apiOperationDes);
            logger.info("请求地址:{}",url);
            logger.info("请求方法:{}.{}", joinPoint.getSignature().getDeclaringTypeName(), methodName);
            logger.info("请求参数:{}",JsonUtils.javaBeanToString(joinPoint.getArgs()));//这里使用任意的Json转换工具即可
            result = joinPoint.proceed();
            logger.info("请求{}模块的{}服务end",apiDes,apiOperationDes);
        } catch (Throwable e) {
            logger.error("进行日志切入失败,失败原因:{}", e);
        }
        return result;
    }
}
Micronaut框架提供了生成OpenAPI Swagger文档的功能。要在Micronaut项目中生成OpenAPI Swagger文档,你可以按照以下步骤进行操作: 1. 首先,确保你的Micronaut项目中已经添加了Swagger支持的依赖。在你的构建工具(如Gradle或Maven)的配置文件中,添加以下依赖: Gradle: ```groovy implementation 'io.swagger.core.v3:swagger-core:2.1.1' implementation 'io.swagger.core.v3:swagger-jaxrs2:2.1.1' implementation 'io.swagger.core.v3:swagger-annotations:2.1.1' ``` Maven: ```xml <dependency> <groupId>io.swagger.core.v3</groupId> <artifactId>swagger-core</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>io.swagger.core.v3</groupId> <artifactId>swagger-jaxrs2</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>io.swagger.core.v3</groupId> <artifactId>swagger-annotations</artifactId> <version>2.1.1</version> </dependency> ``` 2. 在你的Micronaut应用程序的配置文件中,添加以下配置: ```yaml micronaut: application: openapi: paths: # 设置OpenAPI文档生成的路径 spec: /swagger ``` 3. 在你的Micronaut应用程序的控制器类或方法上,使用Swagger注解来描述API的信息,例如: ```java import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @Controller("/api") @Tag(name = "Example") public class ExampleController { @Get(value = "/hello", produces = MediaType.TEXT_PLAIN) @Operation(summary = "Say hello") public String hello() { return "Hello World!"; } } ``` 4. 启动你的Micronaut应用程序,并访问`http://localhost:port/swagger`,其中`port`是你应用程序的端口号。你将能够看到生成的OpenAPI Swagger文档,并可以在Swagger UI中浏览和测试API。 以上就是在Micronaut项目中生成OpenAPI Swagger文档的基本步骤。通过使用Swagger注解,你可以进一步定制和描述你的API。请注意,这只是Micronaut生成OpenAPI Swagger文档的一种方法,你也可以使用其他工具或插件来实现相似的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值