二十八、面向對象底層邏輯-SpringMVC九大組件之ViewResolver接口設計

在 Spring MVC 框架中,視圖解析器(ViewResolver)是連接控制器邏輯與具體視圖技術的核心紐帶。它通過抽象化的接口設計,將視圖的渲染邏輯與業務邏輯解耦,使開發者能夠靈活支持 JSP、Thymeleaf、FreeMarker 等多種視圖技術,同時保持框架的高度擴展性。本文將從接口設計的角度,深入探討?ViewResolver?的設計哲學、實現機制及其在 Spring MVC 架構中的核心價值。


一、設計背景與核心問題

在 Web 應用開發中,控制器的職責是處理請求并返回邏輯視圖名稱(如?"home"?或?"user/profile"),而如何將邏輯視圖名稱轉換為具體的視圖對象(如 HTML 頁面、JSON 數據),則屬于視圖層的職責。早期的 MVC 框架往往將視圖解析邏輯硬編碼在控制器或前端控制器中,導致以下問題:

  1. 技術耦合:更換視圖技術(如從 JSP 切換到 Thymeleaf)需要修改大量代碼。

  2. 擴展困難:新增自定義視圖類型(如 PDF 導出)需侵入框架核心邏輯。

  3. 配置冗余:不同視圖技術的配置分散,難以統一管理。

ViewResolver 的設計目標,是通過策略模式(Strategy Pattern)抽象視圖解析過程,實現以下目標:

  • 解耦視圖技術與業務邏輯

  • 支持多視圖技術共存

  • 提供統一的擴展接口


二、接口設計的核心思想
1.?單一職責原則(SRP)

ViewResolver?接口僅定義一個核心方法:

public interface ViewResolver {View resolveViewName(String viewName, Locale locale) throws Exception;
}

其唯一職責是將邏輯視圖名稱(viewName)和區域(Locale)解析為具體的?View?對象。這種設計使得每個?ViewResolver?實現類只需關注特定類型的視圖解析邏輯,例如:

  • InternalResourceViewResolver?解析 JSP 頁面。

  • ThymeleafViewResolver?解析 Thymeleaf 模板。

2.?開閉原則(OCP)

通過接口抽象,ViewResolver?允許開發者在不修改現有代碼的前提下,擴展新的視圖解析方式。例如,集成 FreeMarker 只需實現?ViewResolver?并配置對應的?FreeMarkerViewResolver,無需調整控制器或?DispatcherServlet?的邏輯。

3.?模塊化與組合性

Spring MVC 支持同時注冊多個?ViewResolver,并通過?Ordered?接口定義解析器的優先級。這種設計使得應用可以靈活組合多種視圖技術,例如:

  • 優先使用 Thymeleaf 解析 HTML 視圖。

  • 若解析失敗,則回退到 JSP 視圖。

public class ThymeleafViewResolver implements ViewResolver, Ordered {private int order = 1;  // 優先級高于默認的 InternalResourceViewResolver(order=Integer.MAX_VALUE)// 實現 resolveViewName 方法...
}

?3. 接口設計哲學

  • 服務域對象:ViewResolver為服務域對象,以單例模式加載并緩存,單實例服務于所有調用,通過多態將View的包裝過程暴露給擴展者。

  • 實體域對象:resolve方法輸出的View屬于實體域,View的實現需要線程安全,緩存復用實例。

  • 元數據對象:resolve方法的入參是視圖名,屬于View的元數據。


三、核心實現類的設計分析
1.?InternalResourceViewResolver:JSP 的經典支持

這是最常用的視圖解析器,用于解析 JSP 頁面。其設計特點包括:

  • 前綴與后綴配置:通過?setPrefix("/WEB-INF/views/")?和?setSuffix(".jsp")?定義視圖路徑規則。

  • 內部轉發機制:使用?RequestDispatcher?將請求轉發到 JSP 頁面,而非直接渲染,從而支持 JSP 與 Servlet 容器的協作。

public class InternalResourceViewResolver extends UrlBasedViewResolver {protected AbstractUrlBasedView buildView(String viewName) {return new InternalResourceView();  // 實際生成 JSP 視圖對象}
}
2.?ContentNegotiatingViewResolver:內容協商的智能化

此解析器根據請求的媒體類型(如?Accept?頭)自動選擇最佳視圖,支持 RESTful 接口的多格式響應(如 JSON、XML)。其核心設計包括:

  • 視圖解析器委托鏈:將實際解析工作委托給其他?ViewResolver

  • 媒體類型匹配:通過?ContentNegotiationManager?確定客戶端支持的視圖類型。

public class ContentNegotiatingViewResolver implements ViewResolver, Ordered {private List<ViewResolver> viewResolvers;public View resolveViewName(String viewName, Locale locale) {List<View> candidateViews = new ArrayList<>();for (ViewResolver resolver : viewResolvers) {View view = resolver.resolveViewName(viewName, locale);if (view != null) candidateViews.add(view);}// 根據媒體類型選擇最佳視圖return selectBestView(request, candidateViews);}
}
3.?AbstractTemplateViewResolver:模板引擎的統一抽象

針對 Thymeleaf、FreeMarker 等模板引擎,Spring MVC 提供了?AbstractTemplateViewResolver?作為基類,其設計亮點包括:

  • 模板文件定位:統一處理模板路徑、編碼和緩存配置。

  • 模板處理器注入:與具體模板引擎(如?TemplateEngine)解耦,通過子類實現細節。

public abstract class AbstractTemplateViewResolver extends UrlBasedViewResolver {protected abstract AbstractTemplateView buildView(String viewName);
}

四、協作流程與架構整合
1. 視圖解析的完整流程
  1. 控制器返回邏輯視圖名

    @GetMapping("/user")
    public String userProfile(Model model) {model.addAttribute("user", getUser());return "user/profile";  // 邏輯視圖名
    }
  2. DispatcherServlet 調用 ViewResolver:遍歷所有注冊的?ViewResolver,按優先級調用?resolveViewName()

  3. 生成 View 對象:首個成功解析的?ViewResolver?返回?View?實例(如?ThymeleafView)。

  4. 視圖渲染:調用?View.render()?方法,將模型數據寫入響應(如生成 HTML)。

2. 與 View 接口的協作

View?接口定義了渲染行為的抽象:

public interface View {String getContentType();void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;
}
  • 模板引擎視圖:如?ThymeleafView?會調用模板引擎的?process()?方法。

  • 靜態資源視圖:如?ResourceBundleViewResolver?可直接返回文件內容。


五、自定義 ViewResolver 的設計實踐
1. 場景:支持 Markdown 渲染為 HTML

假設需要將控制器返回的 Markdown 文件動態渲染為 HTML 頁面,可通過以下步驟實現:

步驟 1:定義 MarkdownView
public class MarkdownView extends AbstractUrlBasedView {@Overrideprotected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {String markdownContent = loadMarkdownFile(getUrl());  // 加載 .md 文件String html = convertMarkdownToHtml(markdownContent); // 轉換為 HTMLresponse.getWriter().write(html);}
}
步驟 2:實現 MarkdownViewResolver
public class MarkdownViewResolver extends UrlBasedViewResolver {public MarkdownViewResolver() {setViewClass(MarkdownView.class);  // 指定視圖類型setPrefix("/WEB-INF/markdown/");   // Markdown 文件路徑前綴setSuffix(".md");                  // 文件后綴}
}
步驟 3:注冊并配置
@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic MarkdownViewResolver markdownViewResolver() {MarkdownViewResolver resolver = new MarkdownViewResolver();resolver.setOrder(0);  // 優先級高于其他解析器return resolver;}
}
2. 效果驗證

控制器方法返回?"user-guide"?時,MarkdownViewResolver?將解析?/WEB-INF/markdown/user-guide.md?文件并渲染為 HTML。


六、設計啟示與最佳實踐
  1. 接口抽象的價值ViewResolver?和?View?的分離,體現了“抽象接口定義契約,具體實現處理細節”的設計原則。

  2. 組合優于繼承:通過組合多個?ViewResolver?實現多視圖支持,而非通過復雜的繼承體系。

  3. 性能優化:部分?ViewResolver(如?UrlBasedViewResolver)會緩存已解析的?View?對象,避免重復解析開銷。


七、總結

ViewResolver?的設計是 Spring MVC 框架中“面向接口編程”思想的典范。它通過統一的抽象層,將視圖技術的多樣性與業務邏輯解耦,使開發者能夠自由切換、擴展視圖實現,同時保持框架核心的簡潔性。無論是支持主流的模板引擎,還是集成自定義的渲染邏輯,ViewResolver?都展現了一種高度靈活、可擴展的設計模式。理解其設計哲學,不僅有助于更高效地使用 Spring MVC,也為構建可維護、可擴展的系統架構提供了重要參考。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907404.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907404.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907404.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LiveWallpaperMacOS:讓你的 Mac 桌面動起來

隨著桌面美化需求的不斷提升,用戶對于桌面壁紙的要求已經不再局限于靜態圖片。越來越多的 Mac 用戶希望桌面能像 Windows 一樣,擁有動態壁紙,展現個性、提升體驗。LiveWallpaperMacOS 正是這樣一款讓你的 Mac 桌面煥發活力的開源項目。 本文將詳細介紹 LiveWallpaperMacOS …

豆瓣電視劇數據工程實踐:從爬蟲到智能存儲的技術演進(含完整代碼)

通過網盤分享的文件&#xff1a;資料 鏈接: https://pan.baidu.com/s/1siOrGmM4n-m3jv95OCea9g?pwd4jir 提取碼: 4jir 1. 引言 1.1 選題背景 在影視內容消費升級背景下&#xff0c;豆瓣電視劇榜單作為國內最具影響力的影視評價體系&#xff0c;其數據價值體現在&#xff1a…

集成均衡功能電池保護芯片在大功率移動電源的應用,創芯微CM1341-DAT、杰華特JW3312、賽微微電CW1244、中穎SH366006

一文了解集成均衡功能電池保護IC在大功率移動電源的應用 創芯微CM1341-DAT 創芯微CM1341-DAT是一款專用于4串鋰離子/磷酸鐵鋰電池的保護芯片&#xff0c;內置有高精度電壓檢測電路和電流檢測電路。通過檢測各節電池的電壓、充放電電流及溫度等信息&#xff0c;實現電池過充電…

PHP生成pdf方法

1&#xff1a;第一種方法&#xff1a; 主要使用PHP的擴展 【 “spatie/browsershot”: “3.57”】 使用這個擴展生成PDF需要環境安裝以下依賴 1.1&#xff1a;NPM【版本&#xff1a;9.2.0】 1.2&#xff1a;NODE【版本&#xff1a;v18.19.1】 1.3&#xff1a;puppeteer【npm in…

聯通專線加持!億林網絡 24 核 32G 裸金屬服務器,千兆共享帶寬適配中小型企業 IT 架構

在當今數字化時代&#xff0c;企業的業務運營越來越依賴高效、穩定的 IT 架構。對于中小型企業而言&#xff0c;如何在有限的預算內構建強大且可靠的 IT 基礎設施&#xff0c;是一項關鍵挑戰。億林網絡推出的 24 核 32G 裸金屬服務器&#xff0c;搭配聯通專線和千兆共享帶寬&am…

SQL計算列

SqlServer: ALTER TABLE KC_BILLHEAD ADD bill_no AS coalesce(billno , ) PERSISTED; 這是一個SQL語句&#xff0c;用于向表KC_BILLHEAD添加一個計算列bill_no。讓我解釋一下這個語句的各個部分&#xff1a; ALTER TABLE KC_BILLHEAD - 修改表KC_BILLHEAD的結構 ADD bill_n…

利用海外代理IP,做Twitter2026年全球趨勢數據分析

近年來&#xff0c;社交媒體趨勢分析逐漸成為品牌監控、市場洞察和消費者研究的必備工具。而當談到全球趨勢數據分析&#xff0c;很多人都會立即想到 Twitter趨勢&#xff08;逼近連美麗國的總統都喜歡在上面發表自己的看法- -!!!&#xff09;。Twitter趨勢&#xff0c;即Twitt…

【Vue3】Vue3 + TypeScript 中如何區分開發和生產環境的 API 地址(支持 axios 請求

Vue3 TypeScript 中如何區分開發和生產環境的 API 地址&#xff08;支持 axios 請求&#xff09; 在實際項目開發中&#xff0c;我們通常會遇到以下需求&#xff1a; 本地開發時訪問的是本地 API&#xff08;如 http://localhost:3000&#xff09;&#xff1b;上線打包后訪問…

【數據結構】線性表之“雙鏈表(帶頭循環雙向鏈表)”

- 第 99 篇 - Date: 2025 - 05 - 25 Author: 鄭龍浩/仟墨 【數據結構】 續上一篇: 線性表之“單鏈表” 文章目錄 “雙鏈表&#xff08;帶頭雙向循環鏈表&#xff09;” 的實現:分步解釋所有函數&#xff1a;test.cDListNode.hDListNode.c “雙鏈表&#xff08;帶頭雙向循環鏈表…

【學習筆記】Transformer

學習的博客&#xff08;在此致謝&#xff09;&#xff1a; 初識CV - Transformer模型詳解&#xff08;圖解最完整版&#xff09; 1 整體結構 Transformer由Encoder和Decoder組成&#xff0c;分別包含6個block。 Transformer的工作流程大體如下&#xff1a; 獲取每個單詞的em…

[MMU]IOMMU的主要職能及詳細的驗證方案

IOMMU的主要職能及詳細的驗證方案 摘要&#xff1a;IOMMU&#xff08;Input/Output Memory Management Unit&#xff09;是一種硬件組件&#xff0c;負責管理I/O設備對內存的直接訪問&#xff08;DMA&#xff0c;Direct Memory Access&#xff09;&#xff0c;其主要作用是提供…

動物類 如何使用Yolov11訓練使用牛羊數據集 實現對牛羊進行檢測數據集

牛羊檢測數據集 3700張 平視視角牛羊檢測 帶標注 voc yolo 牛羊檢測數據集 3700張 牛羊檢測平視 帶標注 voc yolo 分類名: (圖片張數&#xff0c;標注個數) cattle: (1395&#xff0c;4309) sheep: (2393&#xff0c;1 1205) 總數: (3791&#xff0c; 15514) 總類(nc): 2類 以…

搭建frp內網穿透

前言 內網穿透的原理我就不多說了哈&#xff0c;既然會看到我這篇文章&#xff0c;想必都知道內網穿透是做什么的吧 frp分為服務端和客戶端&#xff0c;服務端一般是搭在公網服務器中&#xff0c;客戶端一般搭在本地或者局域網&#xff0c;需要提前在服務端搭好ftp server&am…

Tailwind CSS 實戰,基于 Kooboo 構建 AI 對話框頁面(四):語音識別輸入功能

基于前三章的內容&#xff0c;開發AI 對話框語音識別輸入功能&#xff1a; Tailwind css實戰&#xff0c;基于Kooboo構建AI對話框頁面&#xff08;一&#xff09;-CSDN博客 Tailwind css實戰&#xff0c;基于Kooboo構建AI對話框頁面&#xff08;二&#xff09;&#xff1a;實…

ollama list模型列表獲取 接口代碼

ollama list模型列表獲取 接口代碼 curl http://localhost:11434/v1/modelscoding package hcx.ollama;/*** ClassName DockerOllamaList* Description TODO* Author dell* Date 2025/5/26 11:31* Version 1.0**/import java.io.BufferedReader; import java.io.InputStreamR…

ISOLAR軟件生成報錯處理(五)

錯誤1 An error has occurred. See error log for more details. java.lang.NullPointerException 這東西不用管&#xff0c;不影響生成 錯誤2 Description Resource Path Location Type Target ARObject: <xxxx> CompuMethod used for floating-point data conversi…

前端開發定時,ES學習,java集合

1.前端vue3加入定時任務&#xff1a; import { onMounted, ref,onUnmounted } from vue;//初始化&#xff0c;結束調用部分引用let timer: any;//定時器onMounted(async () > {timer setInterval(() > {open()//需要定時的任務}, 60000)//一分鐘調用一次}); onUnmounte…

Photoshop2025(PS2025)軟件及安裝教程

在數字圖像編輯領域&#xff0c;Adobe Photoshop 一直是無可爭議的王者。如今&#xff0c;Photoshop 2025 重磅登場&#xff0c;再次為我們帶來了驚喜與變革&#xff0c;進一步鞏固了它在行業中的領先地位。 Photoshop 2025 在人工智能方面的升級令人矚目。其全新的 “Magic Se…

【SQL Server Management Studio 連接時遇到的一個錯誤】

第一次用SQL Server Management Studio啟動之后第一步就是要建立連接 但是不知道Server Name要填什么&#xff0c;看了網上的教程說是要找到下面這個注冊表中對應的實例名稱填上去&#xff0c;或者前面加localhost 但是好像都沒有用&#xff0c;一直遇到報錯如下&#xff1a;…

高等數學基礎(向量矩陣及其創建和特殊的矩陣)

向量 向量是機器學習最底層的組成部分, 也是基礎數據的表示形式, 線性代數通過將研究對象拓展到向量, 對多維數據進行統一研究, 而進化出的方法方便我們可以研究和解決真實世界中的問題 標量 標量也稱為"無向量", 使用一個單獨的數表示數值大小, 可以有正負之分, …