Spring 不僅是應用框架,更是一個成熟的工具庫。本文精選文件資源操作、Web 容器集成、Servlet 輔助、過濾器/監聽器四大領域的核心工具類,展示如何用 Spring 方式簡化基礎設施代碼。
org.springframework.core.io.Resource 接口統一封裝文件系統、類路徑、ServletContext、URL 等異構資源。
// 1. 文件系統絕對路徑
Resource res1 = new FileSystemResource("D:/app/conf/file1.txt");
// 2. 類路徑相對路徑(最常用)
Resource res2 = new ClassPathResource("conf/file1.txt");
// 3. Web 應用根目錄相對路徑
Resource res3 = new ServletContextResource(servletContext, "/WEB-INF/classes/conf/file1.txt");
// 4. 遠程 URL
Resource res4 = new UrlResource("https://example.com/config.json");
統一 API:getInputStream()、getFile()、getFilename()、createRelative(path)。
// 支持 classpath:、file:、http: 等前綴
File f1 = ResourceUtils.getFile("classpath:conf/file1.txt");
File f2 = ResourceUtils.getFile("file:D:/app/conf/file1.txt");
// 無需顯式選擇 Resource 實現類,自動路由
LocalizedResourceHelper helper = new LocalizedResourceHelper();
Resource msgUS = helper.findLocalizedResource("i18n/message", ".properties", Locale.US);
Resource msgCN = helper.findLocalizedResource("i18n/message", ".properties", Locale.CHINA);
// 自動解析 message_en_US.properties、message_zh_CN.properties
一行代碼完成各類拷貝場景,避免手寫流操作樣板代碼。
Resource res = new ClassPathResource("conf/file1.txt");
// 文件 → byte[]
byte[] data = FileCopyUtils.copyToByteArray(res.getFile());
// 文件 → String(指定編碼需配合 EncodedResource)
String text = FileCopyUtils.copyToString(new FileReader(res.getFile()));
// 文件 → 文件
FileCopyUtils.copy(res.getFile(), new File("target/file2.txt"));
// InputStream → OutputStream
FileCopyUtils.copy(res.getInputStream(), new ByteArrayOutputStream());
// Reader → Writer
FileCopyUtils.copy(new FileReader(src), new FileWriter(dest));
// 直接從類路徑加載,無需手動獲取 InputStream
Properties props = PropertiesLoaderUtils.loadAllProperties("jdbc.properties");
// 合併加載到現有 Properties
PropertiesLoaderUtils.fillProperties(existingProps, new ClassPathResource("override.properties"));
Resource res = new ClassPathResource("conf/file1.txt");
EncodedResource encRes = new EncodedResource(res, "UTF-8"); // 指定編碼
String content = FileCopyUtils.copyToString(encRes.getReader()); // 必須用 getReader()
// 避免中文亂碼,不依賴操作系統默認編碼
// 推薦:強制要求容器存在,失敗快速
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(servletContext);
// 非推薦:可能返回 null,後續 NPE 隱患
WebApplicationContext wac = WebApplicationContextUtils
.getWebApplicationContext(servletContext);
| 場景 | 傳統寫法 | WebUtils 簡化 |
|---|---|---|
| 獲取 Session 屬性 | request.getSession().getAttribute("key") | WebUtils.getSessionAttribute(request, "key") |
| 獲取 Cookie | 手動遍歷 request.getCookies() | WebUtils.getCookie(request, "name") |
| 獲取真實路徑 | servletContext.getRealPath("/") | WebUtils.getRealPath(servletContext, "/") |
| 獲取臨時目錄 | 手動拼接 | WebUtils.getTempDir(servletContext) 返回 File |
| 暴露請求屬性給轉發目標 | 手動 request.setAttribute() | WebUtils.exposeRequestAttributes(request, map) |
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate5.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
將 Hibernate Session 綁定到請求線程,覆蓋整個 Web 請求週期,Service 層事務結束後 View 層仍可觸發懶加載。適用於 HibernateTransactionManager / JtaTransactionManager 環境。
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name><param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name><param-value>true</param-value>
</init-param>
</filter>
forceEncoding=true 強制覆蓋請求/響應編碼,配合 JSP pageEncoding="UTF-8" 實現全鏈路 UTF-8。
ServletContextRequestLoggingFilter:記錄到 Commons Logging / Log4jServletContextRequestLoggingFilter:記錄到 ServletContext 日誌輸出請求 URI、ServletPath、PathInfo、RealPath、RequestURI 等診斷信息,調試神器。
<context-param>
<param-name>webAppRootKey</param-name><param-value>myapp.root</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.WebAppRootListener</listener-class>
</listener>
啟動後 System.getProperty("myapp.root") 返回 Web 根絕對路徑。第三方庫(如 Log4j)可用 ${myapp.root} 占位符引用。
注意:Tomcat 等共享 JVM 系統屬性的容器,多應用部署時webAppRootKey必須唯一(如app1.root、app2.root),否則後部署者覆蓋先部署者。不解壓 WAR 的容器(WebLogic)無法使用。
<context-param>
<param-name>log4jConfigLocation</param-name><param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
功能包含 WebAppRootListener,無需重複聲明。Log4j 配置中直接用 ${myapp.root}/WEB-INF/logs/app.log。
<listener>
<listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
</listener>
應用關閉時清理 Introspector 緩存,釋放類加載器引用。針對 Struts 1、Quartz 等依賴 Introspector 的框架導致的類加載器無法 GC 問題。Spring 管理的 Bean 無此問題(自有緩存策略)。
Spring 工具類的核心價值在於:用框架級的健壯性、統一性、可測試性,替換散落在業務代碼中的基礎設施樣板。從 Resource 抽象統一異構存儲,到 FileCopyUtils 消除流操作模板,再到過濾器/監聽器聲明式解決橫切關注點,每個工具類都是「最佳實踐的固化」。建議團隊建立「Spring 工具類速查手冊」,新人入職必讀,代碼評審必檢。