SpringCloud Alibaba微服務實戰(zhàn)之業(yè)務日志組件
本文轉載自微信公眾號「JAVA日知錄」,作者單一色調。轉載本文請聯(lián)系JAVA日知錄公眾號。
概述
在單體項目中如果我們需要記錄操作日志一般會通過如下手段實現(xiàn):
- 建立一個自定義注解,標注業(yè)務操作類型
- 通過AOP組裝日志實體,完成日志的收集工作
具體實現(xiàn)可以參考如下的文章鏈接:
http://javadaily.cn/articles/2020/05/13/1589330750429.html
但是在微服務架構中我們不可能每個服務都寫一個自定義注解,再寫一個AOP,這很明顯違反了 Don’t repeat yourself 精神。所以這時候我們一般都會建立一個公共的組件,在公共組件中完成日志的收集,后端服務只需要引入這個公共的組件即可。
這就是今天文章的內容,獨立的業(yè)務日志收集組件。
SpringBoot Starter
要實現(xiàn)上述的功能我們需要借助SringBoot Starter來實現(xiàn),SpringBoot 的一大優(yōu)勢就是Starter,通過Starter我們可以封裝公共的業(yè)務邏輯以及參數(shù)的初始化,如果你在進行微服務開發(fā),Starter的編寫是一定要掌握的。
這里我們簡單提一下SpringBoot Starter實現(xiàn)自動化配置的流程
- spring-boot啟動的時候會找到starterjar包中的resources/META-INF/spring.factories文件,根據(jù)spring.factories文件中的配置,找到需要自動配置的類,xxxAutoConfigure
- 通過xxxAutoConfigure上的注解@EnableConfigurationProperties將當前模塊的屬性綁定到「Environment」 上(若有)。
- 通過xxxAutoConfigure中定義的bean自動裝配到IOC容器中。
實戰(zhàn)
過程如下:
首先我們在項目中建立一個starter的module,如cloud-component-logging-starter
編寫配置類SysLogAutoConfigure
- @Configuration
- public class SysLogAutoConfigure {
- @Bean
- public SysLogAspect controllerLogAspect(){
- return new SysLogAspect();
- }
- }
在SysLogAutoConfigure中我們注入了一個日志切面SysLogAspect,由于日志收集工具不需要額外配置屬性,所以我們也就不需要定義屬性配置類了。
自定義日志注解 SysLog
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface SysLog {
- /**
- * 日志內容
- * @return {String}
- */
- String value();
- }
定義日志切面 SysLogAspect
- @Aspect
- public class SysLogAspect {
- private final Logger log = LoggerFactory.getLogger(this.getClass());
- @Pointcut("@annotation(com.javadaily.component.logging.annotation.SysLog)")
- public void logPointCut() {
- }
- @Around("logPointCut()")
- public Object around(ProceedingJoinPoint pjp) throws Throwable {
- MethodSignature signature = (MethodSignature) pjp.getSignature();
- Method method = signature.getMethod();
- //類名
- String className = pjp.getTarget().getClass().getName();
- //方法名
- String methodName = signature.getName();
- SysLog syslog = method.getAnnotation(SysLog.class);
- //操作
- String operator =syslog.value();
- long beginTime = System.currentTimeMillis();
- Object returnValue = null;
- Exception ex = null;
- try {
- returnValue = pjp.proceed();
- return returnValue;
- } catch (Exception e) {
- ex = e;
- throw e;
- } finally {
- long cost = System.currentTimeMillis() - beginTime;
- if (ex != null) {
- log.error("[class: {}][method: {}][operator: {}][cost: {}ms][args: {}][發(fā)生異常]",
- className, methodName, operator, pjp.getArgs(), ex);
- } else {
- log.info("[class: {}][method: {}][operator: {}][cost: {}ms][args: {}][return: {}]",
- className, methodName, operator, cost, pjp.getArgs(), returnValue);
- }
- }
- }
- }
上面的切面表示,對于使用了@SysLog注解的方法自動進行日志收集,將日志輸入到日志文件。
在resource/META-INF目錄下建立spring.factories文件,加載配置類SysLogAutoConfigure
- org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- com.javadaily.component.logging.configure.SysLogAutoConfigure
在微服務中引入日志組件
- <dependency>
- <groupId>com.jianzh5.cloud</groupId>
- <artifactId>cloud-component-logging-starter</artifactId>
- <version>1.0.0</version>
- </dependency>
在需要進行日志收集的方法上添加@SysLog注解
- @SysLog("查找用戶")
- public ResultData<AccountDTO> getByCode(@PathVariable(value = "accountCode") String accountCode){
- log.warn("get account detail,accountCode is :{}",accountCode);
- SecurityUser securityUser = SecurityUtils.getUser();
- log.info(securityUser);
- AccountDTO accountDTO = accountService.selectByCode(accountCode);
- return ResultData.success(accountDTO);
- }
小結
通過上面7步我們完成了日志收集組件的自定義Starter編寫,這里可能有的同學會問,在 SysLogAutoConfigure類中不是有了 @Configuration和 @Bean注解,這兩個注解不是可以自動加載定義的Bean到IOC容器嗎?為什么還需要通過在spring.factories文件中導入 SysLogAutoConfigure呢?
這是因為springboot項目默認只會掃描本項目下的帶@Configuration注解的類,如果自定義starter,不在本工程中,是無法加載的,所以要配置META-INF/spring.factories配置文件,通過spring.factories來裝載配置類。