1. 程式人生 > >第六章 註解式控制器詳解——SpringMVC強大的資料繫結(2)

第六章 註解式控制器詳解——SpringMVC強大的資料繫結(2)

6.6.2、@RequestParam繫結單個請求引數值

@RequestParam用於將請求引數區資料對映到功能處理方法的引數上。

public String requestparam1(@RequestParam String username)

請求中包含username引數(如/requestparam1?username=zhang),則自動傳入。

此處要特別注意:右擊專案,選擇“屬性”,開啟“屬性對話方塊”,選擇“Java Compiler”然後再開啟的選項卡將“Add variable attributes to generated class files”取消勾選,意思是不將區域性變數資訊新增到類檔案中,如圖6-12所示:


 圖6-12

當你在瀏覽器輸入URL,如“requestparam1?username=123”時會報如下錯誤

Name for argument type [java.lang.String] not available, and parameter name information not found in class file either,表示得不到功能處理方法的引數名,此時我們需要如下方法進行入參:

public String requestparam2(@RequestParam("username") String username)

 即通過@RequestParam("username")明確告訴Spring Web MVC使用username進行入參。

接下來我們看一下@RequestParam註解主要有哪些引數:

value引數名字,即入參的請求引數名字,如username表示請求的引數區中的名字為username的引數的值將傳入;

required是否必須,預設是true,表示請求中一定要有相應的引數,否則將報404錯誤碼;

defaultValue預設值,表示如果請求中沒有同名引數時的預設值,預設值可以是SpEL表示式,如“#{systemProperties['java.vm.version']}”。

public String requestparam4(@RequestParam(value="username",required=false) String username) 
 表示請求中可以沒有名字為username的引數,如果沒有預設為null,此處需要注意如下幾點:

     原子型別:必須有值,否則丟擲異常,如果允許空值請使用包裝類代替。

     Boolean包裝型別型別:預設Boolean.FALSE,其他引用型別預設為null。

public String requestparam5(
@RequestParam(value="username", required=true, defaultValue="zhang") String username) 

表示如果請求中沒有名字為username的引數,預設值為“zhang”。

如果請求中有多個同名的應該如何接收呢?如給使用者授權時,可能授予多個許可權,首先看下如下程式碼:

public String requestparam7(@RequestParam(value="role") String roleList)

如果請求引數類似於url?role=admin&rule=user,則實際roleList引數入參的資料為“admin,user”,即多個數據之間使用“,”分割;我們應該使用如下方式來接收多個請求引數:

public String requestparam7(@RequestParam(value="role") String[] roleList)

public String requestparam8(@RequestParam(value="list") List<String> list)    

 到此@RequestParam我們就介紹完了,以上測試程式碼在cn.javass.chapter6.web.controller. paramtype.RequestParamTypeController中。

6.6.3、@PathVariable繫結URI模板變數值

@PathVariable用於將請求URL中的模板變數對映到功能處理方法的引數上。

@RequestMapping(value="/users/{userId}/topics/{topicId}")
public String test(
       @PathVariable(value="userId") int userId, 
       @PathVariable(value="topicId") int topicId) 

 如請求的URL為“控制器URL/users/123/topics/456”,則自動將URL中模板變數{userId}和{topicId}繫結到通過@PathVariable註解的同名引數上,即入參後userId=123、topicId=456。程式碼在PathVariableTypeController中。

6.6.4、@CookieValue繫結Cookie資料值

@CookieValue用於將請求的Cookie資料對映到功能處理方法的引數上。

public String test(@CookieValue(value="JSESSIONID", defaultValue="") String sessionId) 

如上配置將自動將JSESSIONID值入參到sessionId引數上,defaultValue表示Cookie中沒有JSESSIONID時預設為空。

public String test2(@CookieValue(value="JSESSIONID", defaultValue="") Cookie sessionId)       

傳入引數型別也可以是javax.servlet.http.Cookie型別。

測試程式碼在CookieValueTypeController中。@CookieValue也擁有和@RequestParam相同的三個引數,含義一樣。

6.6.5、@RequestHeader繫結請求頭資料

@RequestHeader用於將請求的頭資訊區資料對映到功能處理方法的引數上。

@RequestMapping(value="/header")
public String test(
       @RequestHeader("User-Agent") String userAgent,
       @RequestHeader(value="Accept") String[] accepts)

     如上配置將自動將請求頭“User-Agent”值入參到userAgent引數上,並將“Accept”請求頭值入參到accepts引數上。測試程式碼在HeaderValueTypeController中。

@RequestHeader也擁有和@RequestParam相同的三個引數,含義一樣。

6.6.6、@ModelAttribute繫結請求引數到命令物件

@ModelAttribute具有如下三個作用:

     ①繫結請求引數到命令物件:放在功能處理方法的入參上時,用於將多個請求引數繫結到一個命令物件,從而簡化繫結流程,而且自動暴露為模型資料用於檢視頁面展示時使用。其實@ModelAttribute此處對於供檢視頁面展示來說與model.addAttribute("attributeName", abc);功能類似。

public String test(@ModelAttribute("user") UserModel user) 

     此處多了一個註解@ModelAttribute("user"),它的作用是將該繫結的命令物件以“user”為名稱新增到模型物件中供檢視頁面展示使用。我們此時可以在檢視頁面使用${user.username}來獲取繫結的命令物件的屬性。

     ②暴露@RequestMapping 方法返回值為模型資料:放在功能處理方法的返回值上時,是暴露功能處理方法的返回值為模型資料,用於檢視頁面展示時使用。

public @ModelAttribute("user2") UserModel test3(@ModelAttribute("user2") UserModel user)

     大家可以看到返回值型別是命令物件型別,而且通過@ModelAttribute("user2")註解,此時會暴露返回值到模型資料( 名字為user2 ) 中供檢視展示使用

 

@ModelAttribute 註解的返回值會覆蓋@RequestMapping 註解方法中的@ModelAttribute 註解的同名命令物件

      ③暴露表單引用物件為模型資料:放在處理器的一般方法(非功能處理方法)上時,是為表單準備要展示的表單引用物件,如註冊時需要選擇的所在城市等,而且在執行功能處理方法(@RequestMapping 註解的方法)之前,自動新增到模型物件中,用於檢視頁面展示時使用;

6.6.7、@SessionAttributes繫結命令物件到session

        有時候我們需要在多次請求之間保持資料,一般情況需要我們明確的呼叫HttpSession的API來存取會話資料,如多步驟提交的表單。Spring Web MVC提供了@SessionAttributes進行請求間透明的存取會話資料。

//1、在控制器類頭上新增@SessionAttributes註解
@SessionAttributes(value = {"user"})    //①
public class SessionAttributeController 

//2、@ModelAttribute註解的方法進行表單引用物件的建立
@ModelAttribute("user")    //②
public UserModel initUser() 

//3、@RequestMapping註解方法的@ModelAttribute註解的引數進行命令物件的繫結
@RequestMapping("/session1")   //③
public String session1(@ModelAttribute("user") UserModel user)

//4、通過SessionStatus的setComplete()方法清除@SessionAttributes指定的會話資料
@RequestMapping("/session2")   //③
public String session(@ModelAttribute("user") UserModel user, SessionStatus status) {
    if(true) { //④
        status.setComplete();
    }
    return "success";
} 

 

 

 

 

 

 

@SessionAttributes(value = {"user"})含義:

@SessionAttributes(value = {"user"}) 標識將模型資料中的名字為“user” 的物件儲存到會話中(預設HttpSession),此處value指定將模型資料中的哪些資料(名字進行匹配)儲存到會話中,此外還有一個types屬性表示模型資料中的哪些型別的物件儲存到會話範圍內,如果同時指定value和types屬性則那些名字和型別都匹配的物件才能儲存到會話範圍內。

包含@SessionAttributes執行流程如下所示:

 首先根據@SessionAttributes註解資訊查詢會話內的物件放入到模型資料中;

 執行@ModelAttribute註解的方法:如果模型資料中包含同名的資料,則不執行@ModelAttribute註解方法進行準備表單引用資料,而是使用①步驟中的會話資料;如果模型資料中不包含同名的資料,執行@ModelAttribute註解的方法並將返回值新增到模型資料中;

③ 執行@RequestMapping方法,繫結@ModelAttribute註解的引數:查詢模型資料中是否有@ModelAttribute註解的同名物件,如果有直接使用,否則通過反射建立一個;並將請求引數繫結到該命令物件;

此處需要注意:如果使用@SessionAttributes註解控制器類之後,③步驟一定是從模型物件中取得同名的命令物件,如果模型資料中不存在將丟擲HttpSessionRequiredException Expected session attribute ‘user’(Spring3.1)

或HttpSessionRequiredException Session attribute ‘user’ required - not found in session(Spring3.0)異常。

 如果會話可以銷燬了,如多步驟提交表單的最後一步,此時可以呼叫SessionStatus物件的setComplete()標識當前會話的@SessionAttributes指定的資料可以清理了,此時當@RequestMapping功能處理方法執行完畢會進行清理會話資料。