請一定掌握SpringBoot這四個高級開發技巧
環境:SpringBoot3.2.5
1. 輸出所有Controller接口信息
有時,為了更便捷地排查問題,我們可能希望在容器啟動時能夠打印出當前項目中所有的Controller接口信息。這樣做可以提供一個清晰的項目接口概覽,從而幫助我們更快速地定位和解決可能出現的問題。
方式1
logging:
level:
web: trace
輸出結果
圖片
雖然達到了目的,但是這將所有web分組的日志都進行輸出了,日志信息非常多,我們所期望的僅僅是輸出Controller相關的信息。
方式2
logging:
level:
'[_org.springframework.web.servlet.HandlerMapping.Mappings]': debug
輸出結果
圖片
通過上面的設置,此時日志信息只輸出了Controller接口,其它的都按照默認的輸出。
2. 統計接口調用耗時
一般我們在不借助第三方工具的情況下,打印接口耗時通常會在接口處理邏輯的開始和結束位置分別記錄當前時間戳,然后計算時間差來獲取耗時,如下示例:
@GetMapping("/time")
public Object time() throws Exception {
Instant startTime = Instant.now() ;
// TODO, 業務操作
System.err.printf("接口耗時: %d 毫秒%n", (Duration.between(startTime, Instant.now()).toMillis())) ;
return "take time" ;
}
上面統計了耗時情況,但是不夠準確,為了更準確地反應處整個請求處理過程的耗時,包括Spring框架根據請求查找對應的Controller、攔截器執行等操作,SpringMVC在這些過程執行完成后是發布了一個事件,我們可以通過監聽該事件來獲取整個請求生命周期的耗時,如下示例:
@Component
public class TakeTimeCountListener implements ApplicationListener<ServletRequestHandledEvent> {
@Override
public void onApplicationEvent(ServletRequestHandledEvent event) {
Throwable failureCause = event.getFailureCause() ;
if (failureCause != null) {
System.err.printf("錯誤原因: %s%n", failureCause.getMessage()) ;
}
System.err.printf("請求客戶端地址:%s, 請求URL: %s, 請求Method: %s, 請求耗時: %d%n",
event.getClientAddress(),
event.getRequestUrl(),
event.getMethod(),
event.getProcessingTimeMillis()) ;
}
}
通過監聽ServletRequestHandledEvent事件,可以有效的獲取客戶端地址,請求的URL等完整的信息,其中ProcessingTimeMillis屬性反應的就是這個請求耗時情況。
圖片
是不是非常的方便及準確!
3. 動態注冊靜態資源
通常情況下,一般都是在配置文件中或者自定義WebMvcConfigurer進行靜態資源的配置及注冊,如下示例:
spring:
web:
resources:
static-locations: classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
以上是默認的路徑,我們可以在這自定義自己的今天資源路徑。如下添加文件系統目錄
spring:
web:
resources:
static-locations: ..., file:///d:/images/
也可以通過編程的方式注冊靜態資源
public class WebConfig implements WebMvcConfigurer {
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/images/**").addResourceLocations("file:///d:\\images\\") ;
}
}
以上方式都是實現配置或代碼中定義好,這都需要重啟服務,無法做到實時生效。要想實時生效可以通過如下方式動態注冊
@RestController
public class RegController {
@Resource
private SimpleUrlHandlerMapping resourceHandlerMapping ;
@Resource
private ApplicationContext context ;
// 如:requestURI=/s/**, path=d:/images/
@GetMapping("")
public Object reg(String requestURI, String path) throws Throwable {
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
handler.setLocations(List.of(new FileSystemResource(path))) ;
handler.setApplicationContext(context) ;
handler.afterPropertiesSet() ;
resourceHandlerMapping.registerHandler(requestURI, handler);
return "register success";
}
}
通過如上方式動態注冊靜態資源,你也可以對相應的靜態資源進行刪除。
4. 容器啟動完成操作
當你希望Spring容器正確初始化加載完成以后,執行一些操作,那么你可以監聽ContextRefreshedEvent事件。該實際的觸發是在refresh方法執行的最后階段。
@Component
public class ContextRefreshedListener implements ApplicationListener<ContextRefreshedEvent> {
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
System.out.println("上下文刷新完成...") ;
// TODO
}
}
通過監聽該事件,你可以在這里實現你自己的邏輯。