一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

SpringBoot源碼解析-升級(jí)版自定義Starter

 碼農(nóng)9527 2021-07-28

分享分享

點(diǎn)贊

有用

返回

上一篇文章中,我們學(xué)習(xí)了如何自定義一個(gè)Starter,而今天要給大家分享的是復(fù)雜點(diǎn)的自定義Starter。  

SpringBoot源碼解析-升級(jí)版自定義Starter

需求  

自定義一個(gè)記錄接口請(qǐng)求的Starter。  

創(chuàng)建Starter項(xiàng)目  

創(chuàng)建一個(gè)名為javafamily-log-spring-boot-starter項(xiàng)目。  

1.引入依賴  

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 <optional>true</optional>
</dependency>
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 <optional>true</optional>
</dependency>
<dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <optional>true</optional>
</dependency>12345678910111213141516171819復(fù)制代碼類型:[java]

2.自定義日志注解  

package com.javafamily.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;// 作用于方法級(jí)別@Target(ElementType.METHOD)// 設(shè)置注解生命周期@Retention(RetentionPolicy.RUNTIME)public @interface JavaFamilyLog { /**
  * 描述接口作用
  */
 String remark() default ""; /**
  * 是否開(kāi)啟時(shí)間打印 默認(rèn)開(kāi)啟
  */
 boolean enable() default true;
}1234567891011121314151617181920212223復(fù)制代碼類型:[java]

注解里面包含兩個(gè)屬性,remark表示接口作用描述,enable表示是否開(kāi)啟接口耗時(shí)的記錄,默認(rèn)為開(kāi)啟,該屬性用于測(cè)試對(duì)比。  

3.自定義攔截器  

package com.javafamily.interceptor;import com.fasterxml.jackson.databind.ObjectMapper;import com.javafamily.annotation.JavaFamilyLog;import lombok.extern.slf4j.Slf4j;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.ModelAndView;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.lang.reflect.Method;@Slf4jpublic class JavaFamilyInterceptor extends HandlerInterceptorAdapter { // 記錄請(qǐng)求起始時(shí)間
 private static final ThreadLocal<Long> START_TIME_THREAD_LOCAL = new ThreadLocal<>(); // 使用jackson序列化
 private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); /**
  * 前置處理
  *
  * @param request
  * @param response
  * @param handler
  * @return
  * @throws Exception
  */
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  if (handler instanceof HandlerMethod) {
   HandlerMethod handlerMethod = (HandlerMethod) handler;
   Method method = handlerMethod.getMethod();   // 獲取方法上的JavaFamilyLog注解
   JavaFamilyLog javaFamilyLog = method.getAnnotation(JavaFamilyLog.class);   if (javaFamilyLog != null) { // 開(kāi)啟打印功能才記錄時(shí)間
 if (javaFamilyLog.enable()) {  // 獲取當(dāng)前時(shí)間作為請(qǐng)求接口開(kāi)始時(shí)間
  long startTime = System.currentTimeMillis();  // 將開(kāi)始時(shí)間存儲(chǔ)到ThreadLocal中
  START_TIME_THREAD_LOCAL.set(startTime);
 }
   }
  }  return true;
 } /**
  * 后置處理
  *
  * @param request
  * @param response
  * @param handler
  * @param modelAndView
  * @throws Exception
  */
 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  if (handler instanceof HandlerMethod) {
   HandlerMethod handlerMethod = (HandlerMethod) handler;
   Method method = handlerMethod.getMethod();
   JavaFamilyLog javaFamilyLog = method.getAnnotation(JavaFamilyLog.class);   if (javaFamilyLog != null) { // 定義方法執(zhí)行耗時(shí)
 long executionTime = -1; // 開(kāi)啟時(shí)間記錄
 if (javaFamilyLog.enable()) {  // 獲取當(dāng)前時(shí)間作為截止時(shí)間
  long endTime = System.currentTimeMillis();  // 從獲取開(kāi)始時(shí)間
  long startTime = START_TIME_THREAD_LOCAL.get();
  START_TIME_THREAD_LOCAL.remove();  // 計(jì)算方法執(zhí)行耗時(shí)
  executionTime = endTime - startTime;
 } // 獲取請(qǐng)求路徑
 String requestUri = request.getRequestURI(); // 獲取方法所在的類路徑以及方法名 通過(guò)#拼接 效果直觀
 String methodFullPath = method.getDeclaringClass().getName() + "#" + method.getName(); // 獲取接口作用描述
 String remark = javaFamilyLog.remark(); // 將參數(shù)轉(zhuǎn)換成字符串
 String parameters = OBJECT_MAPPER.writeValueAsString(request.getParameterMap()); // 打印日志
 log.info("\n接口作用描述:{}\n請(qǐng)求路徑: {}\n方法路徑: {}\n請(qǐng)求參數(shù):{}\n接口耗時(shí):{} ms",
   remark, requestUri, methodFullPath, parameters, executionTime == -1 ? null : executionTime);
   }
  }
 }
}12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394復(fù)制代碼類型:[java]

自定義攔截器中使用jackson序列化對(duì)象,習(xí)慣fastjson的小伙伴可以相應(yīng)依賴替換。整體的思路就是被請(qǐng)求的方法上是否加了JavaFamilyLog注解,如果加了就對(duì)接口請(qǐng)求信息緯度進(jìn)行記錄,同時(shí)需要判斷時(shí)間記錄是否開(kāi)啟,如果不開(kāi)啟就不記錄。  

4.添加自定義攔截器  

package com.javafamily.config;import com.javafamily.interceptor.JavaFamilyInterceptor;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class JavaFamilyLogAutoConfiguration implements WebMvcConfigurer { @Override
 public void addInterceptors(InterceptorRegistry registry) {  // 添加自己實(shí)現(xiàn)的攔截器
  registry.addInterceptor(new JavaFamilyInterceptor());
 }
}1234567891011121314151617復(fù)制代碼類型:[java]

5.編寫(xiě)配置文件  

在resources文件夾下創(chuàng)建META-INF文件夾,在META-INF文件夾下創(chuàng)建spring.factories文件。  

org.springframework.boot.autoconfigure.EnableAutoConfiguration=  com.javafamily.config.JavaFamilyLogAutoConfiguration12復(fù)制代碼類型:[java]

項(xiàng)目整體如下:  

SpringBoot源碼解析-升級(jí)版自定義Starter

引入自定義Starter  

創(chuàng)建任意SpringBoot工程,引入javafamily-log-spring-boot-starter依賴。

<dependency>
 <groupId>com.javafamily</groupId>
 <artifactId>javafamily-log-spring-boot-starter</artifactId>
 <version>0.0.1-SNAPSHOT</version>
</dependency>12345復(fù)制代碼類型:[java]

創(chuàng)建HelloController,對(duì)剛寫(xiě)完的自定義Starter進(jìn)行測(cè)試。  

package com.javafamily.familydemo.controller;import com.javafamily.annotation.JavaFamilyLog;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestControllerpublic class HelloController { @JavaFamilyLog(remark = "/關(guān)閉時(shí)間打印測(cè)試", enable = false)
 @GetMapping("/test")
 public String test() {  return "success";
 } @JavaFamilyLog(remark = "日志測(cè)試")
 @GetMapping("/logTest")
 public String logTest(String name) {  return "Hello " + name;
 }
}123456789101112131415161718192021222324復(fù)制代碼類型:[java]

接著分別請(qǐng)求兩個(gè)方法,我們看下效果。  

2021-07-28 19:03:03.257  INFO 14580 --- [nio-8080-exec-6] c.j.interceptor.JavaFamilyInterceptor : 
接口作用描述:/關(guān)閉時(shí)間打印測(cè)試
請(qǐng)求路徑: /test
方法路徑: com.javafamily.familydemo.controller.HelloController#test
請(qǐng)求參數(shù):{}
接口耗時(shí):null ms2021-07-28 19:03:04.677  INFO 14580 --- [nio-8080-exec-7] c.j.interceptor.JavaFamilyInterceptor : 
接口作用描述:日志測(cè)試
請(qǐng)求路徑: /logTest
方法路徑: com.javafamily.familydemo.controller.HelloController#logTest
請(qǐng)求參數(shù):{"name":["JavaFamily"]}
接口耗時(shí):5 ms123456789101112復(fù)制代碼類型:[java]

根據(jù)效果,我們可以看到test接口耗時(shí)為null說(shuō)明enable屬性生效了,logTest接口也打印了請(qǐng)求參數(shù),說(shuō)明自定義Starter的功能都實(shí)現(xiàn)了。同時(shí)日志中也包含了接口請(qǐng)求一些重要的緯度信息,大家可以根據(jù)自己的需求再添加一些緯度。  

好了,本篇文章到此結(jié)束,我們下次見(jiàn)。  

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    欧美黑人在线一区二区| 亚洲精品成人福利在线| 欧美精品中文字幕亚洲| 欧美人妻少妇精品久久性色| 日本久久精品在线观看| 一本久道久久综合中文字幕| 亚洲精品中文字幕一二三| 精品国产av一区二区三区不卡蜜| 一区二区三区亚洲国产| 亚洲av一区二区三区精品| 免费一级欧美大片免费看| 中日韩免费一区二区三区| 久久热在线免费视频精品| 亚洲一区二区三区三州| 老司机亚洲精品一区二区 | 亚洲人午夜精品射精日韩| 国产欧美日韩精品成人专区| 91亚洲精品亚洲国产| 国产精品免费视频视频| 欧美日韩在线视频一区| 深夜日本福利在线观看| 色好吊视频这里只有精| 97人摸人人澡人人人超碰| 中字幕一区二区三区久久蜜桃| 国产午夜精品美女露脸视频| 国产欧美日韩精品成人专区| 99久久国产综合精品二区| 亚洲三级视频在线观看免费| 亚洲国产91精品视频| 午夜福利大片亚洲一区| 一区二区日本一区二区欧美| 国产又色又爽又黄的精品视频| 十八禁日本一区二区三区| 麻豆亚州无矿码专区视频| 亚洲中文字幕高清乱码毛片| 欧美自拍偷自拍亚洲精品| 日韩av欧美中文字幕| 亚洲永久一区二区三区在线| 国产精品一区二区丝袜| 2019年国产最新视频| 国产精品一区二区三区欧美|