day05-3-springmvc中ModelAndView的詳解


ModelAndView的作用非常簡單,就是兩個作用。

第一個作用,往作用域中放值。

第二個作用,實現頁面跳轉。

15 - ModelAndView簡單使用

往request作用域中放值,有三種方式。

springmvc中提供了一個類,就是modelandview。model是模型。項目中的實體類,裝載傳輸數據。view是視圖,幫助我們設置視圖,操作視圖。

image-20211006183444474

modelandview的構造器很多,如上圖所示。

有參構造器當中的參數,說明modelandview的類當中,肯定是有對應的屬性,肯定是有這些屬性的set和get方法的。

image-20211006183603776

model-and-view的add-object方法

image-20211006183706304

我們看上圖中的,第二個方法。

我們說過model-and-view當中的model是用來裝載和傳輸數據的。

那么里面addObject方法,就是裝載和傳輸數據的過程。

image-20211006183934202

我們前面通過return "success"這種方式,返回的就是視圖名稱。

現在我們通過modelAndView類setViewName的方法,也可以設置視圖名稱。

image-20211006184230803

所以,我們必須將ModelAndView對象,返回:

image-20211006184327719

我們在request作用域中放了一個值,然后跳轉到了success.jsp,然后我們就可以在success.jsp當中獲取到request作用域中的值。

jsp當中jstl是c標簽

el表達式是為了從作用域中取值,pagecontext,request,session,Application四個作用域。從小到大逐個作用域尋找。

image-20211006184559849

image-20211006184830846

我們可以加上作用域。

image-20211006185016152

測試效果如下:

image-20211006184624294

所以:modelandview的作用是裝載數據,是往作用域中放置,view是設置視圖名稱,實現頁面跳轉。

16 - ModelAndView源碼調試

加載spring-webmvc的源碼,查看ModelAndView里面的東西。

image-20211006191216727

我們看一下:

image-20211006191334724

image-20211006191353845

image-20211006200936174

  • getModelInternal
  • getModelMap
  • getModel
  • 這三個方法是一樣的,都是獲取model對象,model就是一個map,就是多個鍵值對數據。

debug - 斷點

image-20211006201103555

image-20211006201210876

image-20211006201315546

image-20211006201402838

點擊yes之后,進入到下面的視圖:

image-20211006201443200

調整視圖布局,變成下面的樣子:

image-20211006201618595

  • 雙擊打斷點,debug模式啟動項目,進入debug視圖,在debug框框中,顯示的是,執行到斷點位置,已經調用的方法。

image-20211006201933818

1、DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse)

image-20211006202141898

  • 上面的代碼中有一個mv,這個mv就是ModelAndView。
  • 我們的代碼中,打斷點的位置,是要返回一個ModelAndView對象。
  • 這里的代碼,意思就是通過ha.handle()方法,對請求進行了處理,獲得了一個mv對象。

image-20211006202555427

為什么是空的,因為這一行,還沒有開始執行。斷點所在的位置,是還沒有執行的。

image-20211006202900999

我們怎么從mv的代碼的地方,走到processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);的地方呢?

image-20211006203319369

我們想要從mv的地方跑到processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);的地方

  • 第一,我們可以通過step over一步一步執行。
  • 第二,我們可以在processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);位置,打一個斷點,然后點擊resume,就可以直接跳到我們需要的位置。

image-20211006203610677

在這個位置,mv的值是,如下圖所示:

image-20211006213436834

2、進入processDispatchResult方法內部

進入方法內部,兩種方式:

  • 第一,按住ctrl鍵,鼠標點進去。
  • 第二,step into。如果當前位置,有多個方法被調用,會按照方法執行的順序,一個一個地進入。

image-20211006204154816

我們在render(mv, request, response);位置打一個斷點,然后resume到render的位置,然后step into進去。

3、進入render方法內部

在這個render方法內部,已經把mv當中的view和model分開處理了。

image-20211006204946713

view.render(mv.getModelInternal(), request, response);的位置,我們打一個斷點,然后step into進入看看。

4、進入view.render()方法內部

view.render(mv.getModelInternal(), request, response);

這一行中有兩個方法,render()是一個方法,mv.getModelInternal()也是一個方法。

我們點擊step into之后,是mv.getModelInternal()這個方法先執行。

第一次,step into,進入mv.getModelInternal()方法內部。

image-20211006210609156

第二次,step into,回到render方法的位置。

image-20211006210706864

第三次,step into,這次是真正進入到render方法內部:

image-20211006211252380

5、進入renderMergedOutputModel()方法內部

image-20211006211637140

6、進入exposeModelAsRequestAttributes()方法內部

image-20211006212135875

然后不斷step over,從這個exposeModelAsRequestAttributes()方法中出來。

7、回到renderMergedOutputModel()方法內部

ModelAndView的作用就是兩個:第一往作用域中放值,第二實現頁面跳轉。

原來我們在servlet當中,往作用域中放值,和實現頁面跳轉,分別是這么寫的。

request.setAttribute(key, value),往作用域中放值。

request.getRequestDispatcher.forward(),實現頁面跳轉

image-20211006213014077

ModelAndView源碼調試總結

image-20211006215318599

17 - 三種方式實現作用域放值

前面說過,往作用域中放值,是三種方式。

第一種方式

image-20211006220056618

	@RequestMapping(value="/param",method=RequestMethod.POST)
	public ModelAndView param() {
		ModelAndView mav = new ModelAndView();
		mav.addObject("username", "root");
		mav.setViewName("success");
		return mav;
	}

第二種方式

image-20211006220544991

	@RequestMapping(value="/param",method=RequestMethod.POST)
	public String param(Map<String, Object> map) {
		map.put("username", "admin");
		return "success";
	}

這種寫法,默認也會將上面的map和return “success”包裝成為ModelAndView對象的。

第三種方式

image-20211006221545549

	@RequestMapping(value="/param",method=RequestMethod.POST)
	public String param(Model model) {
		model.addAttribute("username", "zhangsan");
		return "success";
	}

通過model往作用域中放值,也會將model和"success"封裝成為ModelAndView對象的

總結

springmvc處理請求過程中,往作用域中放值,有以下三種方式:

  • map.put("username","admin")
  • Model.addAttribute("username","admin")
  • ModelAndView.addObject("username","admin")

上面三種寫法,都會和view一起封裝到ModelAndView中。

當前亂碼問題

  • 頁面發送請求,傳值張三

image-20211006222039744

  • 我們在控制層的方法當中,接收了頁面傳值,看到控制台輸出是亂碼的:

image-20211006222304638

  • 作用域中放的值,頁面顯示是正常的。

image-20211006222143925

為什么頁面傳值,控制層接收打印會亂碼呢?

這是因為第一,頁面傳值的時候,默認會以頁面的編碼為編碼格式。我們頁面傳過去的username默認是以utf-8編碼的。

但是tomcat接收數據的時候,默認是用iso-8859-1來接收的。

springmvc為我們提供了一個編碼過濾器,只要配置一下,就可以了。這個以后再說。

2019年6月17日 - day05 - 下午 - 結束


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM