天天看點

《Spring 5 官方文檔》18. Web MVC 架構(十一)

you can configure how spring mvc determines the requested media types from the request. the available options are to check the url path for a file extension, check the “accept” header, a specific query parameter, or to fall back on a default content type when nothing is requested. by default the path extension in the request uri is checked first and the “accept” header is checked second.

below is an example of customizing content negotiation options through the mvc java config:

in the mvc namespace, the <code>&lt;mvc:annotation-driven&gt;</code> element has a <code>content-negotiation-manager</code> attribute, which expects a <code>contentnegotiationmanager</code>that in turn can be created with a <code>contentnegotiationmanagerfactorybean</code>:

if not using the mvc java config or the mvc namespace, you’ll need to create an instance of <code>contentnegotiationmanager</code> and use it to configure <code>requestmappinghandlermapping</code> for request mapping purposes, and <code>requestmappinghandleradapter</code> and <code>exceptionhandlerexceptionresolver</code> for content negotiation purposes.

note that <code>contentnegotiatingviewresolver</code> now can also be configured with a <code>contentnegotiationmanager</code>, so you can use one shared instance throughout spring mvc.

in more advanced cases, it may be useful to configure multiple <code>contentnegotiationmanager</code> instances that in turn may contain custom<code>contentnegotiationstrategy</code> implementations. for example you could configure <code>exceptionhandlerexceptionresolver</code> with a <code>contentnegotiationmanager</code>that always resolves the requested media type to <code>"application/json"</code>. or you may want to plug a custom strategy that has some logic to select a default content type (e.g. either xml or json) if no content types were requested.

this is a shortcut for defining a <code>parameterizableviewcontroller</code> that immediately forwards to a view when invoked. use it in static cases when there is no java controller logic to execute before the view generates the response.

an example of forwarding a request for <code>"/"</code> to a view called <code>"home"</code> in java:

而且在xml中使用相同的<code>&lt;mvc:view-controller&gt;</code>元素:

mvc配置簡化了視圖解析器的注冊。

以下是一個java配置示例,它使用freemarker html模闆配置内容協商視圖分辨率,并将jackson作為<code>view</code>json渲染的預設值:

和xml一樣:

不過請注意,freemarker,tiles,groovy markup和腳本模闆也需要配置底層視圖技術。

mvc命名空間提供專用元素。例如與freemarker:

在java配置中,隻需添加相應的“configurer”bean:

此選項允許在特定url模式之後的靜态資源請求由位置<code>resourcehttprequesthandler</code>清單中的任何一個<code>resource</code>提供。這提供了一種友善的方式來從除web應用程式根以外的位置(包括類路徑上的位置)提供靜态資源。該<code>cache-period</code>屬性可用于設定遠期未來的到期标頭(1年是優化工具的推薦,如page speed和yslow),以便用戶端更有效地利用它們。處理程式也正确地評估<code>last-modified</code>标題(如果存在),以便适當地<code>304</code>傳回狀态代碼,避免用戶端已經緩存的資源的不必要的開銷。例如,<code>/resources/**</code><code>public-resources</code>

為了在未來1年的時間内為這些資源提供服務,以確定最大限度地利用浏覽器緩存并減少浏覽器發出的http請求:

在xml中:

該<code>mapping</code>屬性必須是可以被使用的螞蟻圖案 <code>simpleurlhandlermapping</code>,并且<code>location</code>屬性必須指定一個或多個有效的資源目錄位置。可以使用逗号分隔的值清單來指定多個資源位置。指定的位置将按照指定的順序檢查是否存在任何給定請求的資源。例如,要啟用來自web應用程式根目錄和類路徑<code>/meta-inf/public-web-resources/</code>中任何jar中已知路徑 的資源的使用,請執行以下操作:

當部署新版本的應用程式時可能會更改的資源時,建議您将版本字元串合并到用于請求資源的映射模式中,以便您可以強制用戶端請求新部署的應用程式資源版本。版本化url的支援内置在架構中,可以通過在資源處理程式上配置資源鍊來啟用。該鍊由<code>resourceresolver</code> 一個或多個<code>resourcetransformer</code>執行個體之後的一個執行個體組成。他們一起可以提供任意解決和資源轉型。

内置<code>versionresourceresolver</code>可配置不同的政策。例如,<code>fixedversionstrategy</code>可以使用屬性,日期或其他作為版本。a <code>contentversionstrategy</code>使用從資源的内容計算的md5哈希(稱為“指紋識别”url)。請注意,<code>versionresourceresolver</code>在服務資源時,會自動将解析的版本字元串用作http etag标頭值。

<code>contentversionstrategy</code>是一個很好的預設選擇,除非不能使用(例如使用javascript子產品加載器)的情況。您可以針對不同的模式配置不同的版本政策,如下所示。請記住,計算基于内容的版本是昂貴的,是以在生産中應該啟用資源鍊緩存。

java配置示例

xml示例:

為了使上述工作,應用程式還必須使用版本來呈現url。最簡單的方法是配置 <code>resourceurlencodingfilter</code>其中包含響應并覆寫其<code>encodeurl</code>方法。這将在jsp,freemarker以及調用響應<code>encodeurl</code>方法的任何其他視圖技術中起作用 。或者,應用程式還可以直接注入和使用 <code>resourceurlprovider</code>bean,該bean将自動使用mvc java配置和mvc命名空間聲明。

還支援webjars <code>webjarsresourceresolver</code>,當<code>"org.webjars:webjars-locator"</code>庫位于類路徑時,webjars會自動注冊。該解析器允許資源鍊從http get請求中解析版本不可知庫 <code>"get /jquery/jquery.min.js"</code>将傳回資源<code>"/jquery/1.2.0/jquery.min.js"</code>。它也可以通過在模闆中重寫資源url來實作<code>&lt;script src="/jquery/jquery.min.js"/&gt; → &lt;script src="/jquery/1.2.0/jquery.min.js"/&gt;</code>。

這允許映射<code>dispatcherservlet</code>到“/”(進而覆寫容器的預設servlet的映射),同時仍允許靜态資源請求由容器的預設servlet處理。它<code>defaultservlethttprequesthandler</code>使用“/ **”的url映射和相對于其他url映射的最低優先級來配置。

該處理程式将所有請求轉發到預設servlet。是以,重要的是按照所有其他url的順序保持最後<code>handlermappings</code>。如果您使用<code>&lt;mvc:annotation-driven&gt;</code>或者如果您正在設定自己的自定義<code>handlermapping</code>執行個體,請確定将其<code>order</code>屬性設定為低于該值的值<code>defaultservlethttprequesthandler</code>,否則将是這種情況<code>integer.max_value</code>。

要使用預設設定啟用該功能,請使用:

或在xml中:

覆寫“/”servlet映射的注意事項是,<code>requestdispatcher</code>預設的servlet必須通過名稱而不是路徑檢索。該 <code>defaultservlethttprequesthandler</code>會嘗試自動檢測在啟動時容器中的預設的servlet,使用大多數主要的servlet容器(包括軟體tomcat,jetty的glassfish,jboss和樹脂中,weblogic和websphere)已知名稱的清單。如果預設的servlet已經使用不同的名稱自定義配置,或者如果使用了預設servlet名稱未知的其他servlet容器,那麼必須明确地提供預設的servlet名稱,如下例所示:

以下是java配置中的一個示例:

和xml一樣,使用<code>&lt;mvc:path-matching&gt;</code>元素:

以下是使用自定義<code>objectmapper</code>而不是預設值添加jackson json和xml轉換器的示例 :

《Spring 5 官方文檔》18. Web MVC 架構(十一)

其他有趣的傑克遜子產品可用:

也可以在xml中執行相同的操作:

從上述示例可以看出,mvc java配置和mvc命名空間提供了不需要深入了解為您建立的基礎bean的更進階别的構造。相反,它可以幫助您專注于您的應用程式需求。但是,在某些時候,您可能需要更細緻的控制,或者您可能隻想了解底層配置。

更精細控制的第一步是檢視為您建立的基礎bean。在mvc java配置中,您可以看到javadoc和其中的<code>@bean</code>方法 <code>webmvcconfigurationsupport</code>。此類中的配置通過注釋自動導入<code>@enablewebmvc</code>。其實如果你打開<code>@enablewebmvc</code>你可以看到<code>@import</code>聲明。

更精細控制的下一步是定制一個在其中建立的bean之一<code>webmvcconfigurationsupport</code>或可能提供您自己的執行個體的屬性。這需要兩件事情 – 删除<code>@enablewebmvc</code>注釋,以防止導入,然後從<code>delegatingwebmvcconfiguration</code>一個子類 擴充<code>webmvcconfigurationsupport</code>。這是一個例子:

《Spring 5 官方文檔》18. Web MVC 架構(十一)

應用程式應該隻有一個配置擴充<code>delegatingwebmvcconfiguration</code> 或單個<code>@enablewebmvc</code>注釋類,因為它們都注冊了相同的底層bean。以這種方式修改bean不會阻止您使用本節前面顯示的任何更進階别的構造。<code>webmvcconfigureradapter</code>子類和 <code>webmvcconfigurer</code>實作仍在使用中。

對您建立的配置的細粒度控制對于mvc命名空間來說有點困難。

如果您确實需要這樣做,而不是複制其提供的配置,請考慮配置一個<code>beanpostprocessor</code>檢測要按類型自定義的bean,然後根據需要修改其屬性。例如:

請注意,<code>mypostprocessor</code>需要将其包含在其中<code>&lt;component scan/&gt;</code>以便檢測到它,或者如果您喜歡,可以使用xml bean聲明明确聲明它。