當控制器處理完請求時,通常會將包含視圖名稱或視圖對象以及一些模型屬性的ModelAndView對象返 回到DispatcherServlet。因此,經常需要在控制器中構造ModelAndView對象。ModelAndView類提供了幾個重載的構造 器和一些方便的方法,讓你可以根據自己的喜好來構造ModelAndView對象。這些構造器和方法以類似的方式支持視圖名稱和視圖對象。
當只有一個模型屬性要返回時,可以在構造器中指定該屬性來構造ModelAndView對象:
package com.apress.springrecipes.court.web; ... import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class WelcomeController extends AbstractController{ public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception{ Date today = new Date(); return new ModelAndView("welcome","today",today); } }
如果有不止一個屬性要返回,可以先將它們傳遞到一個Map中再來構造ModelAndView對象。
package com.apress.springrecipes.court.web; ... import org.springframework.web.servlet.ModelAndView; import org. springframework.web.servlet.mvc.AbstractController; public class ReservationQueryController extends AbstractController{ ... public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception{ ... Map<String,Object> model = new HashMap<String,Object>(); if(courtName != null){ model.put("courtName",courtName); model.put("reservations",reservationService.query(courtName)); } return new ModelAndView("reservationQuery",model); } }
Spring也提供了ModelMap,這是java.util.Map實現,可以根據模型屬性的具體類型自動生成模型屬性的名稱。
package com.apress.springrecipes.court.web; ... import org.springframework.ui.ModelMap; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class ReservationQueryController extends AbstractController{ ... public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception{ ... ModelMap model = new ModelMap(); if(courtName != null){ model.addAttribute("courtName",courtName); model.addAttribute("reservations",reservationService.query(courtName)); } return new ModelAndView("reservationQuery",model); } }
由於這兩個模型屬性的類型為String和List<Reservation>,ModelMap會為它們生成默認的名稱----string和reservationList。如果你不喜歡這些名稱,可以顯式地指定它們。
構造完ModelAndView對象之后,仍然可以利用addobject()方法為它添加模型屬性。這個方法返回ModelAndView對象
本身,因此可以在一個語句中構造ModelAndView對象。請注意,你也可以省略addObject()方法的屬性名稱。在這種情況下,這個方法會與ModeMap生成相同的屬性名稱。
package com.apress.springrecipes.court.web; ... import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class ReservationQueryController extends AbstractController{ ... public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response)throws Exception{ .... List<Reservation> reservations = null; if(courtName != null){ reservations = reservationService.query(courtName); } return new ModelAndView("reservationQuery","courtName",courtName) .addObject("reservations",reservations); } }
事實上,返回的模型和視圖都是可選的。在有些情況下,你只返回視圖,模型中沒有任何屬性。或者只返回模型,讓Spring MVC根據請求URL來決定視圖。有時候,如果讓控制器直接處理HttpServletResponse對象,甚至可以返回null,例如在將二進制文件返回給用戶的時候。
補充:ModelAndView的構造方法
構造方法
第一種:ModelAndView(String viewName)
最簡單的ModelAndView是只有View的名稱,之后View名稱被View resolver,也就是org.springframework.web.servlet.View的實例解析,例如 InternalResourceView或JstlView等等。
第二種:ModelAndView(String viewName, Map model)
如果您要返回呈現畫面時所需的Model資料,則可以使用Map來收集呈現View時所需的資料,然后在建構ModelAndView作為建構時的參數。
第三種:ModelAndView(String viewName, String modelName, Object modelObject)
返回單個model時使用。
第四種:ModelAndView()
不指定view,也不指定modelName,只向里面添加數據
向ModelAndView添加對象時可以不用指定鍵(key),單一對象的鍵取決於類名,比如x.y.User的鍵是user,而某一類對象的 Set、List或數組則稍有些復雜,取第一個對象的類名加上“List”作為它的鍵,比如這里的articles是一個存放Article對象的 List,它的鍵就是articleList;具體的視圖會根據請求自動在指定目錄中尋找對應的視圖文件,本例中就會尋找listarticle(后綴由配置文件決定)。
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { List<Article> articles = articleService.loadAllArticles(); ModelAndView mav = new ModelAndView(); mav.addObject(articles); return mav; }