天天看點

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

該<code>@responsebody</code>注釋是類似<code>@requestbody</code>。該注釋可以放在一個方法上,并訓示傳回類型應該直接寫入http響應體(而不是放在模型中,或者解釋為視圖名稱)。例如:

上述示例将導緻文本<code>hello world</code>被寫入http響應流。

控制器實作rest api是一個非常常見的用例,是以僅提供json,xml或定制的mediatype内容。為友善起見,您可以使用以下<code>@requestmapping</code>方式<code>@responsebody</code>來注釋您的控制器類,而不是注釋所有 方法<code>@restcontroller</code>。

這<code>httpentity</code>是相似的<code>@requestbody</code>和<code>@responsebody</code>。除了通路請求和響應主體之外<code>httpentity</code>(和響應特定子類<code>responseentity</code>)還允許通路請求和響應頭,如下所示:

上述示例擷取<code>myrequestheader</code>請求标頭的值,并将其作為位元組數組讀取。它将<code>myresponseheader</code>響應添加到<code>hello world</code>響應流中,并将響應狀态代碼設定為201(已建立)。

該<code>@modelattribute</code>注釋可以對方法或方法的參數來使用。本節将介紹其在方法上的用法,下一節将介紹其在方法參數上的用法。

an <code>@modelattribute</code> on a method indicates the purpose of that method is to add one or more model attributes. such methods support the same argument types as <code>@requestmapping</code> methods but cannot be mapped directly to requests. instead <code>@modelattribute</code> methods in a controller are invoked before <code>@requestmapping</code>methods, within the same controller. a couple of examples:

<code>@modelattribute</code>方法用于填充具有常用屬性的模型,例如使用狀态或寵物類型填充下拉清單,或者檢索諸如account的指令對象,以便使用它來表示html表單上的資料。後一種情況在下一節進一步讨論。

注意兩種風格的<code>@modelattribute</code>方法。在第一個方法中,該方法通過傳回它隐式地添加一個屬性。在第二個方法中,該方法接受<code>model</code>并添加任意數量的模型屬性。您可以根據需要選擇兩種風格。

控制器可以有多種<code>@modelattribute</code>方法。所有這些方法都<code>@requestmapping</code>在相同控制器的方法之前被調用。

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

當沒有明确指定模型屬性名稱時會發生什麼?在這種情況下,根據其類型将預設名稱配置設定給模型屬性。例如,如果該方法傳回類型的對象<code>account</code>,則使用的預設名稱為“account”。您可以通過<code>@modelattribute</code>注釋的值更改它。如果直接添加屬性<code>model</code>,請使用适當的重載<code>addattribute(..)</code>方法 – 即,帶有或不帶有屬性名稱。

如上一節所述<code>@modelattribute</code>,可以在方法或方法參數上使用。本節介紹了其在方法參數中的用法。

一個<code>@modelattribute</code>上的方法參數訓示參數應該從模型中檢索。如果模型中不存在,參數首先被執行個體化,然後添加到模型中。一旦出現在模型中,參數的字段應該從具有比對名稱的所有請求參數中填充。這被稱為spring mvc中的資料綁定,這是一種非常有用的機制,可以節省您逐個解析每個表單字段。

鑒于上述例子,寵物執行個體可以從哪裡來?有幾個選擇:

由于<code>@modelattribute</code>在同一控制器中的方法,它可能已經在模型中 – 如上一節所述。

它可以基于uri模闆變量和類型轉換器(下面更詳細地解釋)來檢索。

它可以使用其預設構造函數執行個體化。

一種<code>@modelattribute</code>方法是從資料庫中檢索屬性的常用方法,可以通過使用可選地在請求之間存儲屬性 <code>@sessionattributes</code>。在某些情況下,通過使用uri模闆變量和類型轉換器來檢索屬性可能很友善。這是一個例子:

在此示例中,模型屬性(即“account”)的名稱與uri模闆變量的名稱相比對。如果您注冊<code>converter&lt;string, account&gt;</code>,可以将 <code>string</code>帳戶值轉換為一個<code>account</code>執行個體,則上述示例将無需使用<code>@modelattribute</code>方法。

由于資料綁定,可能會出現錯誤,例如缺少必填字段或類型轉換錯誤。要檢查這些錯誤,請在<code>bindingresult</code>參數後立即添加一個<code>@modelattribute</code>參數:

使用一個<code>bindingresult</code>你可以檢查是否發現錯誤,在這種情況下,渲染相同的形式通常是在spring的<code>&lt;errors&gt;</code> 表單标簽的幫助下顯示錯誤的。

請注意,在某些情況下,在沒有資料綁定的情況下擷取模型中的屬性可能是有用的。對于這種情況,您可以将其注入<code>model</code>控制器,或者使用注釋上的<code>binding</code>标志:

除了資料綁定之外,您還可以使用自己的自定義驗證器調用驗證,傳遞與<code>bindingresult</code>用于記錄資料綁定錯誤相同的驗證器。這允許在一個地方累積資料綁定和驗證錯誤,并随後向使用者報告:

或者您可以通過添加jsr-303 <code>@valid</code> 注釋自動調用驗證:

類型級<code>@sessionattributes</code>注釋聲明特定處理程式使用的會話屬性。這通常将列出模型屬性或模型屬性的類型,這些模型屬性或類型應該透明地存儲在會話或某些會話存儲中,作為後續請求之間的格式支援bean。

以下代碼片段顯示了此注釋的用法,指定了模型屬性名稱:

如果您需要通路全局管理的預先存在的會話屬性,即控制器外部(例如,通過過濾器),并且可能存在或可能不存在,<code>@sessionattribute</code>則會使用方法參數上的注釋:

對于需要添加或删除會話屬性的用例,請考慮注入 <code>org.springframework.web.context.request.webrequest</code>或 <code>javax.servlet.http.httpsession</code>控制方法。

到類似<code>@sessionattribute</code>的<code>@requestattribute</code>注釋可以被用于通路由濾波器或攔截器建立的預先存在的請求屬性:

以前的章節介紹了<code>@modelattribute</code>如何支援浏覽器用戶端的表單送出請求。建議與非浏覽器用戶端的請求一起使用相同的注釋。然而,在使用http put請求時,有一個顯着的差別。浏覽器可以通過http get或http post送出表單資料。非浏覽器用戶端也可以通過http put送出表單。這提出了一個挑戰,因為servlet規範要求<code>servletrequest.getparameter*()</code>一系列方法僅支援http post的表單域通路,而不支援http put。

為了支援http put和patch請求,該<code>spring-web</code>子產品提供了<code>httpputformcontentfilter</code>可以在以下配置中的過濾器 <code>web.xml</code>:

上述過濾器攔截具有内容類型的http put和patch請求<code>application/x-www-form-urlencoded</code>,從請求的正文 中讀取表單資料,并包裝<code>servletrequest</code>以便通過<code>servletrequest.getparameter*()</code>一系列方法使表單資料可用 。

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

由于<code>httpputformcontentfilter</code>消耗了請求的正文,是以不應配置為依賴其他轉換器的put或patch url <code>application/x-www-form-urlencoded</code>。這包括<code>@requestbody multivaluemap&lt;string, string&gt;</code>和<code>httpentity&lt;multivaluemap&lt;string, string&gt;&gt;</code>。

該<code>@cookievalue</code>注釋允許将方法參數綁定到http cookie的值。

讓我們考慮以下cookie已被接收到http請求:

以下代碼示例示範如何擷取<code>jsessionid</code>cookie 的值:

該<code>@requestheader</code>注釋允許将一個方法參數綁定到請求頭。

以下是一個示例請求标頭:

以下代碼示例示範了如何擷取<code>accept-encoding</code>和 <code>keep-alive</code>标題的值:

當<code>@requestheader</code>注解上的使用<code>map&lt;string, string&gt;</code>, <code>multivaluemap&lt;string, string&gt;</code>或<code>httpheaders</code>參數,則地圖被填充有所有标頭值。

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

内置支援可用于将逗号分隔的字元串轉換為字元串或類型轉換系統已知的其他類型的數組/集合。例如,注釋的方法參數<code>@requestheader("accept")</code>可以是類型<code>string</code>,也可以是 <code>string[]</code>或<code>list&lt;string&gt;</code>。