1. 程式人生 > 實用技巧 >Spring中Model、ModelMap、ModelAndView理解和具體使用總結

Spring中Model、ModelMap、ModelAndView理解和具體使用總結

1.隱含模型

在瞭解這三者之前,需要知道一點:SpringMVC在呼叫方法前會建立一個隱含的資料模型,作為模型資料的儲存容器, 成為”隱含模型”。
也就是說在每一次的前後臺請求的時候會隨帶這一個揹包,不管你用沒有,這個揹包確實是存在的,用來盛放我們請求互動傳遞的值;關於這一點,spring裡面有一個註解:
@ModelAttribute :被該註解修飾的方法,會在每一次請求時優先執行,用於接收前臺jsp頁面傳入的引數
例子:


@Controller
public class User1Controller{

private static final Log logger = LogFactory.getLog(User1Controller.class);

// @ModelAttribute修飾的方法會先於login呼叫,該方法用於接收前臺jsp頁面傳入的引數
@ModelAttribute
public void userModel(String loginname,String password,
         Model model){
    logger.info("userModel");
    // 建立User物件儲存jsp頁面傳入的引數
    User2 user = new User2();
    user.setLoginname(loginname);
    user.setPassword(password);
    // 將User物件新增到Model當中
    model.addAttribute("user", user);
}

@RequestMapping(value="/login1")
 public String login(Model model){
    logger.info("login");
    // 從Model當中取出之前存入的名為user的物件
    User2 user = (User2) model.asMap().get("user");
    System.out.println(user);
    // 設定user物件的username屬性
    user.setUsername("測試");
    return "result1";
}

2.Mode和ModelMap的區別

在前端向後臺請求時,spring會自動建立Model與ModelMap例項,我們只需拿來使用即可;

無論是Mode還是ModelMap底層都是使用BindingAwareModelMap,所以兩者基本沒什麼區別;
我們可以簡單看一下兩者區別:

①Model

Model是一個介面,它的實現類為ExtendedModelMap,繼承ModelMap類

public class ExtendedModelMap extends ModelMap implements Model

②ModelMap

ModelMap繼承LinkedHashMap,spring框架自動建立例項並作為controller的入參,使用者無需自己建立

public class ModelMap extends LinkedHashMap

而是對於ModelAndView顧名思義,ModelAndView指模型和檢視的集合,既包含模型 又包含檢視;ModelAndView的例項是開發者自己手動建立的,這也是和ModelMap主要不同點之一;ModelAndView其實就是兩個作用,一個是指定返回頁面,另一個是在返回頁面的同時新增屬性;

3.構造方法對應的使用方法

a 它有很多構造方法,對應會有很多使用方法:
例子:
(1)當你只有一個模型屬性要返回時,可以在構造器中指定該屬性來構造ModelAndView物件:

 public class WelcomeController extends AbstractController{  
    public ModelAndView handleRequestInternal(HttpServletRequest request,  
        HttpServletResponse response)throws Exception{  
        Date today = new Date();  
        return new ModelAndView("welcome","today",today);  
    }  
} 

(2)如果有不止一個屬性要返回,可以先將它們傳遞到一個Map中再來構造ModelAndView物件


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提供的Model或者ModelMap,這是java.util.Map實現;

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);  
    }  
}  

在頁面上可以通過el變數方式${key}或者bboss的一系列資料展示標籤獲取並展示modelMap中的資料;上面主要講了ModelAndView的使用,其實Model與ModelMap使用方法都是一致;

下面我通過一個下例子展示一下:
在spring專案中,在配置檔案中配置好 檢視解析器:

<!-- 檢視解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 字首 -->
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <!-- 字尾 -->
        <property name="suffix" value=".jsp"/>
    </bean>

在後臺寫

    @RequestMapping("/test1")
    public ModelAndView test1(ModelMap mm ,HttpServletRequest request){
        ModelAndView mv = new ModelAndView("mytest");
        mv.addObject("key1","123");
        mm.addAttribute("key1","1234");
        return mv;
    }//前端為 123 123

    @RequestMapping("/test2")
    public String test2(ModelMap mm ,HttpServletRequest request){
        mm.addAttribute("key1", "1234");
        return "mytest";
    }//前端為 1234 1234 

    @RequestMapping("/test3")
    public String test3(Model mm ,HttpServletRequest request){
        mm.addAttribute("key1", "12345");
        return "mytest";
    }

    @RequestMapping("/test4")
    public String test4(Model mm ,HttpServletRequest request){
        mm.addAttribute("key1", "12345");
        request.setAttribute("key1", "123456");
        return "mytest";
    }//前端為 12345 12345

    @RequestMapping("/test5")
    public String test5(Model mm ,ModelMap mmp,HttpServletRequest request){
        request.setAttribute("key1", "123456");
        mm.addAttribute("key1", "12345");
        mmp.addAttribute("key1", "1234567");
        return "mytest";
    }//前端為 1234567 1234567

從上面測試可以看到Model,ModelMap與ModelAndView的具體使用;同時可以看出Model與ModelMap的值是能夠替換的;並且兩者賦值後作用比request.setAttribute()要大;這點在使用時需要注意;具體為啥,估計是最終解析時還是放在request上,最終還是替換了;我們知道

終上所述,我們知道了Model與ModelMap其實都是實現了hashMap,並且用法都是一樣的;兩者都是spring在請求時自動生成,拿來用便可;ModelAndView就是在兩者的基礎上可以指定返回頁面;
賦值能力 ModelAndView > Model/ModelMap>request ;