1. 程式人生 > >SpringMVC學習筆記(未完)

SpringMVC學習筆記(未完)

前邊的入門就不說了~~

如果有不懂的可以參考SpringMVC 4.2.4.RELEASE官方中文API (進入下載頁直接下載)

1、矩陣變數

2、媒體型別
3、請求引數和請求頭(params="myParam=myValue")



4、REST架構
   (1)、HTTP協議4個操作動詞(對應4中基本操作):
     GET(獲取資源)、
     POST(新建資源)、
   PUT(更新資源)、
     DELETE(刪除資源)

       HiddenHttpMethodFilter
    (2)REST架構風格:
          理解本真的REST架構風格--http://kb.cnblogs.com/page/186516
      深入淺出REST--http://www.infoq.com/cn/articles/rest-introduction



5、@SessionAttribute:將資料放到Session域中,該註解只能放到類上面


6、@ModelAttribute 標記的方法,在目標方法執行之前都會被SpringMvc呼叫
   *注意:在@ModelAttribute 標記的方法中,放到Map時的鍵需要和目標方法入參型別的第一個字母小寫的字串一致
   eg.
		@ModelAttribute 
		public void getUser(@RequestParam(value="id") Integer id,Map<String,Object> map){
			//從資料庫中取出物件
			User user=new User();
			System.out.println("從資料庫中獲取一個物件:"+user);
   			 map.put("user",user);
   		 }
		@RequestMapping("/testModelAttribute")
		public String testModelAttribute(User user){
			System.out.println("修改後:"+user);
			return "success";
		} 

以上程式碼執行流程:
1、執行@ModelAttribute 註解修飾的方法:從資料庫中取出物件,把物件放入到Map中,鍵為:user
2、SpringMVC 從Map中去除User物件,並把表單的請求引數賦給該User物件的對應屬性,

3、SpringMVC 把上述物件傳入目標方法(testModelAttribute)的引數。


原始碼分析流程:
1.呼叫@ModelAttribute 註解修飾的方法,實際上吧@ModelAttribute 方法中的Map中的資料放在了implicitModel中
2、解析請求處理器的目標引數,實際上該目標引數來自於WebDataBinder物件的target屬性
1)、建立WebDataBinder物件
  1、確定ObjectName屬性:若傳入attrName屬性值為"",則objectName為類,類名第一個首字母小寫,
                    *注意:attrName.若目標方法的POJO屬性使用了@ModelAttribute來修飾,則attrName值即為@ModelAttribute的value屬性值
  2、確定target屬性
  >在implicizModel中查詢attrName對應的屬性值,若存在,OK
    >若不存在,則驗證當前Handler是否使用了@SessionAttribute進行修飾,若使用了,則嘗試Session中獲取attrName所對應的屬性值.若session中沒有對應的屬性值,則丟擲了異常。
  >若Handler沒有使用@SessionAttributes 進行修飾,或@SessionAttributes 沒有使用value值指定的Key和attrName相匹配,則通過反射建立了POJO物件。
2)、SpringMVC把表單的請求引數賦給了 WebDataBinder 的target對應的屬性,
3)、SpringMVC會把WebDataBinder 的 attrName 的target給到impliciModel,近而傳到request域物件中。

4)、把WebDataBinder的target作為引數傳遞給目標方法的入參。


SpringMVC確定目標方法POJO型別入參的過程:
1、確定一個Key
1)、若目標方法的POJO型別的引數沒有使用@ModelAttribute 作為修飾,則key為POJO類名第一個字母小寫,
2)、若使用了@ModelAttribute 來修飾,則key為@ModelAttribute 註解value的值。
2、在implicitModel中查詢key對應的物件,若存在,則作為入參傳入。
1)、若在@ModelAttribute 標記的方法中在Map中儲存過,且key和1確定的key一致,則會獲取到。
3、若implicitModel中不存在key對應的物件,則檢查當前的Handler是否使用了@SessionAttributes 註解修飾,若使用該註解,且@SessionAttributes 註解的value屬性值中包含了key,則會從HttpSession中獲取key所對應的value值,若存在則直接傳入到目標方法的入參中,若不存在將丟擲異常。
4、若Handler沒有標識@SessionAttributes 註解或@SessionAttributes註解的value 值中不包含key則會通過反射來建立POJO型別的引數,傳入為目標方法的引數。

5、SpringMVC會把 key 和 POJO 型別的物件儲存到implicitModel中,進而會儲存到request中, 


7、自定義檢視
1、在Spring-servlet.xml中配置檢視解析器,
	<!--配置 BeanNameViewResolver 檢視解析器:使用檢視的名字來解析檢視-->
	<!-- 通過order屬性來定義檢視解析器的優先順序,order值越小優先順序越高-->
	<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
	<property name="order" value="100"></property>
	</bean>




8、 SpringMVC的<from:form>
1、使用SpringMVC的<from:form>標籤時,在域物件中必須有一個與表單欄位對應的bean,可以通過form的modelAttribute屬性定義繫結的bean,若不設定預設為command,
eg.
在Controller中:

	@RequestMapping(value="user", method=RequestMethod.GET)
		public String (Map<Strign,Object> map){
			map.put("user",new User());   //將user放到域物件中,
			return "user_add";
		} 


user_add.jsp:
	<form:form action="user" method="POST" modelAttribute="user">
			.....
			//欄位
			//欄位
		</form:form>


2、掌握<form:form>的常用欄位

9、SpringMVC處理靜態資源
1、問題出現:
一般REST風格的URL不會帶.do或.html字尾,若將DispacherServlet請求對映配置為/,則SpringMVC會捕獲WEB容器的所有請求,所以當我 們試圖使用外部的js、css、images等靜態資源時,SpringMVC 會將他們當成一個普通的請求處理,導致找不到對應的處理器而丟擲異常。
2、解決方法:
在SpringMVC的配置檔案中配置<mvc:default-servlet-handler/>,會在SpringMVC上下文中定義一個DefaultServletHttpRequestHandler,
他會對 DispatcherServlet 的請求進行篩選,如果是沒有經過對映的請求,就將該請求交給Web伺服器預設的Servlet處理,如果不是靜態資源的 請求,才由DispatcherServlet繼續處理。一般WEB應用伺服器預設的Servlet名稱都是default,若使用的Servlet名稱不是default,則可以在default- servlet-handler中顯示定義。


10、自定義型別轉換器
在springmvc-servlet.xml中配置:

	<!--配置 ConversionService -->
	<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
		<property name="converters">
			<set>
				<ref bean="自定義型別轉換器類名第一個字母小寫"/>
			</set>
		</property>
	</bean>
	<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>






11、資料格式化
@NumberFormat  數字格式轉換器
@DateFormat   日期格式轉換器
如果轉換出錯,可以用BindingResult類檢視



12、資料校驗

1、使用JSR 303驗證標準
2、加入hibernate validator 的支援(jar包或dependency)
3、在springmvc-servlet.xml在中新增<mvc:annotation-driven/>
4、在bean的屬性上新增相應的註解


5、在目標方法bean型別的前面新增@valid註解


如果填寫資料不符合要求,會出現如下警告


13、處理Json
1、加入jar包或Maven依賴
2、編寫目標方法,使其返回Json對應的物件或集合
3、在目標方法上新增@RequestBody註解


14、異常處理
1、在@ExceptionHandler 標記方法的入參中可以加入Exception型別的引數,該引數即對應發生的異常物件
2、@ExceptionHandler 方法的入參中不能傳入 Map. 若希望把異常資訊傳導頁面上, 需要使用 ModelAndView 作為返回值
eg.

		    @ExceptionHandler({ArithmeticException.class})
		public ModelAndView handleArithmeticException(Exception ex){
			System.out.println("出異常了: " + ex);
			ModelAndView mv = new ModelAndView("error");
			mv.addObject("exception", ex);
			return mv;
		}


3、 @ExceptionHandler 方法標記的異常有優先順序的問題. 
4、@ControllerAdvice: 如果在當前 Handler 中找不到 @ExceptionHandler 方法來出來當前方法出現的異常, 則將去 
@ControllerAdvice 標記的類中查詢 @ExceptionHandler 標記的方法來處理異常. 


5、使用 SimpleMappingExceptionResolver
eg.
	<!-- 配置使用 SimpleMappingExceptionResolver 來對映異常 -->
		<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
		        <!-- exceptionAttribute 屬性預設值為 "exception",在頁面上可以通過${ex}直接獲取異常資訊-->
			<property name="exceptionAttribute" value="ex"></property>
			     <property name="exceptionMappings">
				<props>
				      <prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
				</props>
			     </property>
			</bean>