在日常做项目里,不管是本地调试阶段还是线上正式部署运行阶段, 我们常常需要对接口的被调用做一些参数打印,为了更清晰地去联调以及确认数据。
实现这种场景,无疑第一时间想到的就是aop,配合注解的方式使用,这样确实是个好办法,而且还能更加自由地去监控打印请求接口日志,甚至还能加上一些逻辑校验等。
还有一种就是最普通的,用map接收参数,在每个接口都打印下map。
那么这篇教程里面,介绍的是新的一种方案,实现监控打印请求接口日志, 就是整合ApiBoot Logging 。
先看实战项目最后的结构:
OK,接下来我们直接开始整合:
首先是pom.xml 文件:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.demo</groupId> <artifactId>elegant</artifactId> <version>0.0.1-SNAPSHOT</version> <name>elegant</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <api.boot.version>2.1.4.RELEASE</api.boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.10</version> </dependency> <!--ApiBoot Logging--> <dependency> <groupId>org.minbox.framework</groupId> <artifactId>api-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <!--ApiBoot统一版本依赖 @EnableLoggingClient等使用--> <dependencies> <dependency> <groupId>org.minbox.framework</groupId> <artifactId>api-boot-dependencies</artifactId> <type>pom</type> <scope>import</scope> <version>${api.boot.version}</version> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
ApiBoot Logging 核心依赖是:
接下来是application.yml文件:
#配置项目名称 spring: application: name: ElegantDemo #配置端口 server: port: 8067 #配置ApiBoot Logging 日志组件 api: boot: logging: show-console-log: true #实现美化打印请求日志 format-console-log-json: true
这里有一点需要提醒下, 里面的配置项目名称和端口是有必要的,因为ApiBoot 在监控每次请求的数据输出时,里面包括了项目名称和端口。
然后是在启动类上加上注解 @EnableLoggingClient :
可以看到这个注解,Client ,客户端,没错,这个其实也有对应的admin端进行日志上报,但是目前实现对接口请求的日志监控打印,我们只需要使用客户端组件即可。
接下来,我们来简单编写几个接口,作为测试,LoggingApiTestController.java:
import com.demo.elegant.pojo.Cat; import org.springframework.web.bind.annotation.*; import java.util.Map; /** * @Author : JCccc * @CreateTime : 2019/11/25 * @Description : **/ @RestController public class LoggingApiTestController { @GetMapping("/testGet1") public String testGet1(@RequestParam("name") String name, @RequestParam("age") Integer age) { return "testGet1: name is "+ name+" and age is :"+age; } @GetMapping("/testGet2") public String testGet2(@RequestParam Map paramMap) { return "testGet2: name is "+ paramMap.get("name")+" and age is :"+paramMap.get("age"); } @PostMapping("/testPost1") public String testPost1(@RequestBody Cat cat) { return "testPost1: name is "+ cat.getName()+" and age is :"+cat.getAge(); } @PostMapping("/testPost2") public String testPost2(@RequestBody Map paramMap) { return "testPost2: name is "+ paramMap.get("name")+" and age is :"+paramMap.get("age"); } }
这里其中一个post方法用到了实体类接收参数,顺便也贴一下 Cat.java:
import lombok.Data; /** * @Author : JCccc * @CreateTime : 2019/11/25 * @Description : **/ @Data public class Cat { private String name; private Integer age; }
ok,我们用postman先来调用 ‘/testGet1’ 接口:
可以看到控制台:
红色框里面正是这次请求的所有数据,都成功监控打印了。
蓝色框是啥呢,就是前面说的admin组件,我们这里不需要用到admin,所以会有提示说这个日志监控报告没有找到对应的admin服务,没有影响,直接无视就好。
其余接口就不一一调用了,效果都是一样的。
如果觉得这个日志打印下来占行数太多了,那么可以在application.yml里面,将json格式化给设置为false,默认不设置也是false:
设置格式化为false:到这里,其实已经完了,但是我个人有点强迫症,我不想看到那个warn日志,所以稍微操作一哈。
那么我这里简单使用下logback日志框架,顺便对日志文件输出都进行统一性管理:
新建logback.xml,直接放到resources文件夹下(一般的项目想整合logback框架,基本保留这份xml就够用了,拿来即用):
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true"> <!-- 从application.yml 中注入变量 --> <!-- <springProperty scope="context" name="LOG_PATH" source="log.home"/> --> <!-- <springProperty scope="context" name="APPDIR" source="spring.application.name"/> --> <property name="LOG_PATH" value="./logs"/> <property name="APPDIR" value="elegant"/> <!-- <property name="LOG_PATH" value="/usr/java/apache-tomcat-8.5.47"/>--> <!-- <property name="APPDIR" value="dashboardLog"/>--> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>1-%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger - %msg%n</pattern> <charset>GBK</charset> </encoder> </appender> <!-- error级别日志文件输出,按日期时间滚动记录输出 --> <appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_PATH}/${APPDIR}/log_error.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APPDIR}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>500MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <append>true</append> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern> <charset>utf-8</charset> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>error</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- warn级别日志文件输出,按日期时间滚动记录输出 --> <appender name="FILEWARN" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_PATH}/${APPDIR}/log_warn.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APPDIR}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>2MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <append>true</append> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern> <charset>utf-8</charset> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>warn</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <!-- info级别日志文件输出,按日期时间滚动记录输出 --> <appender name="FILEINFO" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_PATH}/${APPDIR}/log_info.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/${APPDIR}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern> <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> <maxFileSize>2MB</maxFileSize> </timeBasedFileNamingAndTriggeringPolicy> </rollingPolicy> <append>true</append> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern> <charset>utf-8</charset> </encoder> <filter class="ch.qos.logback.classic.filter.LevelFilter"> <level>info</level> <onMatch>ACCEPT</onMatch> <onMismatch>DENY</onMismatch> </filter> </appender> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern> </encoder> </appender> <!--设置为OFF,即屏蔽; 留下sqltiming作为INFO级别输出--> <!-- <logger name="jdbc.connection" level="OFF"/>--> <!-- <logger name="jdbc.resultset" level="OFF"/>--> <!-- <logger name="jdbc.resultsettable" level="OFF"/>--> <!-- <logger name="jdbc.audit" level="OFF"/>--> <!-- <logger name="jdbc.sqltiming" level="OFF"/>--> <!-- <logger name="jdbc.sqlonly" level="INFO"/>--> <!--设置为OFF,即屏蔽--> <logger name="org.minbox.framework.logging.client.admin.report.support.LoggingAdminReportSupport" level="OFF"/> <!--设置日志打印级别为INFO--> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILEINFO"/> <appender-ref ref="FILEWARN"/> <appender-ref ref="FILEERROR"/> </root> </configuration>
这里面包括配置各种等级日志的打印,生成日志文件,配置文件生成路径,以及个性化屏蔽等,有兴趣可以看看我的注释。
其中,我将那个可有可无的warn给直接屏蔽了,
那么我们重新启动下项目,再调用下接口:
再看看控制台的输出:
OK,很满意。
顺带,日志文件也照常输出,而且还能根据日志滚动输出等:
好,这篇教程就到这吧。