javascript
SpringMVC数据绑定全面示例
? ? ? ?已經使用SpringMVC開發了幾個項目,平時也有不少朋友問我數據怎么傳輸,怎么綁定之類的話題,今天做一個總結。在此之前,大家可以看一下我之前的一篇關于Spring restful的文章http://www.xdemo.org/spring-restful/。
項目下載:http://pan.baidu.com/share/link?shareid=955245807&uk=1896630845
首先貼出Controller的全部內容
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | /** ?*?@author?<a?href="http://www.xdemo.org">xdemo.org</a> ?*/ @Controller @RequestMapping(value="/request") public?class?RequestParamController?{ ???????????????? ???????????????/** ????????????????*?最簡的配置,不是用@RequestParam,效果和get2一樣,默認required=false ????????????????*?請求方式不限 ????????????????*?@param?p1 ????????????????*?@param?map ????????????????*/ ???????????????@RequestMapping(value="get0") ???????????????public?void?get0(String?p1,ModelMap?map){ ???????????????????????????????map.addAttribute("p1",?p1);//往頁面傳遞 ???????????????} ???????????????? ???????????????/** ????????????????*?value="p1"表示參數名稱<br> ????????????????*?required=true表示如果沒有傳遞參數"p1",則會報400參數異常<br> ????????????????*?使用void表示約定的路徑,即request/get1.jsp ????????????????*?@param?p1 ????????????????*?@param?map ????????????????*/ ???????????????@RequestMapping(value="get1",method=RequestMethod.GET) ???????????????public?void?get1(@RequestParam(value="p1",required=true)String?p1,ModelMap?map){ ???????????????????????????????map.addAttribute("p1",?p1);//往頁面傳遞 ???????????????} ???????????????? ???????????????/** ????????????????*?和get1不同的是,p1這個參數不一定非得需要,即使不給這個參數,也可以正常運行<br> ????????????????*?返回String是視圖的名稱,只要將map賦值,給的值也會帶到前抬 ????????????????*?@param?p1 ????????????????*?@param?map ????????????????*?@return ????????????????*/ ???????????????@RequestMapping(value="get2",method=RequestMethod.GET) ???????????????public?String?get2(@RequestParam(value="p1",required=false)String?p1,ModelMap?map){ ???????????????????????????????map.addAttribute("p1",?p1);//往頁面傳遞 ???????????????????????????????return?"request/get2"; ???????????????} ???????????????? ???????????????/** ????????????????*?和get2不同的是,返回的對象是ModelAndView ????????????????*?表示綁定了視圖和數據的對象,數據就是ModelMap中的Key-Value ????????????????*?@param?p1 ????????????????*?@param?map ????????????????*?@return ????????????????*/ ???????????????@RequestMapping(value="get3",method=RequestMethod.GET) ???????????????public?ModelAndView?get3(@RequestParam(value="p1",required=false)String?p1,ModelMap?map){ ???????????????????????????????map.addAttribute("p1",?p1); ???????????????????????????????return?new?ModelAndView("request/get2",map); ???????????????} ???????????????? ???????????????/** ????????????????*?跳轉到頁面 ????????????????*?@throws?NoSuchAlgorithmException? ????????????????*/ ???????????????@RequestMapping("userForm") ???????????????public?String?userForm(HttpServletResponse?response)?throws?NoSuchAlgorithmException{ ???????????????????????????????CookieUtils.writeCookie(response,?-1,?"x",?"dddddddddddddd"); ???????????????????????????????return?"request/userForm"; ???????????????} ???????????????? ???????????????/** ????????????????*?綁定數據到User對象,支持Map,Set,List,Array等,但是需要使用下標,不是很靈活 ????????????????*?請查看user2的寫法 ????????????????*?@param?user ????????????????*?@param?map ????????????????*/ ???????????????@RequestMapping(value="user") ???????????????public?void?user(User?user,ModelMap?map){ ???????????????????????????????map.addAttribute("user",?user); ???????????????} ???????????????? ???????????????/** ????????????????*?這里可以接受List,Array,Set等,寫法是一樣的,注意前端寫法<br> ????????????????*?另外這個必須要使用MappingJacksonHttpMessageConverter這個消息轉換器 ????????????????*?請看我上面的配置 ????????????????*?@param?user ????????????????*?@return ????????????????*/ ???????????????@ResponseBody ???????????????@RequestMapping("user2") ???????????????public?String?user2(@RequestBody?List<User>?user){ ???????????????????????????????System.out.println(user.size()); ???????????????????????????????return?""; ???????????????} ???????????????? ???????????????/** ????????????????*?這個方法只支持POST ????????????????*?@param?s ????????????????*?@return ????????????????*/ ???????????????@ResponseBody ???????????????@RequestMapping("array") ???????????????public?String?array(@RequestBody?String[]?s){ ???????????????????????????????System.out.println(s.length); ???????????????????????????????return?""; ???????????????} ???????????????? ???????????????/** ????????????????*?這個比較奇葩,來自一位朋友的寫法,即.xxx/5,4這樣的請求,SpringMVC竟然也是支持的 ????????????????*?@param?id ????????????????*?@return ????????????????*/ ???????????????@ResponseBody ???????????????@RequestMapping(value="array/{id}",method=RequestMethod.GET) ???????????????public?String?array2(@PathVariable("id")Long[]?id){ ???????????????????????????????System.out.println(id.length); ???????????????????????????????return?"array?length:"+id.length+""; ???????????????} ???????????????? ???????????????/** ????????????????*?一個表單對應多個Bean對象,這些Bean中有相同的屬性,那么需要在分裝他們的一個整體的對象 ????????????????*?使之支持object.property的表達式 ????????????????*?@param?c ????????????????*/ ???????????????@ResponseBody ???????????????@RequestMapping("complex") ???????????????public?void?complexObject(C?c){ ???????????????????????????????System.out.println(c.getA().getX()); ???????????????????????????????System.out.println(c.getB().getX()); ???????????????????????????????? ???????????????} ???????????????? ???????????????/** ????????????????*?讀取Cookie的值 ????????????????*?@param?x ????????????????*?@return ????????????????*/ ???????????????@ResponseBody ???????????????@RequestMapping("cookie") ???????????????public?String?cookie(@CookieValue("x")String?x){ ???????????????????????????????return?x; ???????????????} ???????????????? } |
這種方式支持get和post,參數可選
| 1 2 3 4 5 6 7 8 9 10 | /** *?最簡的配置,不是用@RequestParam,效果和get2一樣,默認required=false *?請求方式不限 *?@param?p1 *?@param?map */ @RequestMapping(value="get0") public?void?get0(String?p1,ModelMap?map){ ???????map.addAttribute("p1",?p1);//往頁面傳遞 } |
訪問方式簡單的比如http://localhost:8080/springmvc-param/request/get0?p1=xxx。
?這種方式支持get,參數必須
| 1 2 3 4 5 6 7 8 9 10 11 | /** *?value="p1"表示參數名稱<br> *?required=true表示如果沒有傳遞參數"p1",則會報400參數異常<br> *?使用void表示約定的路徑,即request/get1.jsp *?@param?p1 *?@param?map */ @RequestMapping(value="get1",method=RequestMethod.GET) public?void?get1(@RequestParam(value="p1",required=true)String?p1,ModelMap?map){ ???????map.addAttribute("p1",?p1);//往頁面傳遞 } |
這種方式和第一種不同的是,指定了訪問訪問必須為GET,而且參數是必須的,可以通過如下方式訪問這個地址:http://localhost:8080/springmvc-param/request/get1?p1=xxxx。
這種方式僅支持GET,參數可選
| 1 2 3 4 5 6 7 8 9 10 11 12 | /** *?和get1不同的是,p1這個參數不一定非得需要,即使不給這個參數,也可以正常運行<br> *?返回String是視圖的名稱,只要將map賦值,給的值也會帶到前抬 *?@param?p1 *?@param?map *?@return */ @RequestMapping(value="get2",method=RequestMethod.GET) public?String?get2(@RequestParam(value="p1",required=false)String?p1,ModelMap?map){ ???????map.addAttribute("p1",?p1);//往頁面傳遞 ???????return?"request/get2"; } |
這個方法和第二種唯一不同的就是參數是可選的,其他沒有不同。
?這種方式僅支持GET,參數可選
| 1 2 3 4 5 6 7 8 9 10 11 12 | /** *?和get2不同的是,返回的對象是ModelAndView *?表示綁定了視圖和數據的對象,數據就是ModelMap中的Key-Value *?@param?p1 *?@param?map *?@return */ @RequestMapping(value="get3",method=RequestMethod.GET) public?ModelAndView?get3(@RequestParam(value="p1",required=false)String?p1,ModelMap?map){ ???????map.addAttribute("p1",?p1);//往頁面傳遞 ???????return?new?ModelAndView("request/get2",map); } |
ModelAndView表示綁定了數據的視圖,可以通過EL表達式去取值。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /** ?*?跳轉到頁面 ?*?@throws?NoSuchAlgorithmException? ?*/ @RequestMapping("userForm") public?String?userForm(HttpServletResponse?response)?throws?NoSuchAlgorithmException{ ???????CookieUtils.writeCookie(response,?-1,?"x",?"dddddddddddddd"); ???????return?"request/userForm"; } /** *?讀取Cookie的值 *?@param?x *?@return */ @ResponseBody @RequestMapping("cookie") public?String?cookie(@CookieValue("x")String?x){ ???????return?x; } |
先訪問http://localhost:8080/springmvc-param/request/userForm這個方法,跳轉到一個頁面,并向瀏覽器寫入Cookie,第二個方法訪問的時候即可通過@CookieValue方式來取到Cookie中的值。
綁定數據到一個對象上,支持get和post
一個User,一個Phone,一個User擁有多個Phone,為了演示,User中有一個List和Array的Phone的集合
| 1 2 3 4 5 6 7 8 | public?class?User?{ ???????????????? ???????private?String?userName; ???????private?String?address; ???????private?List<Phone>?phones; ???????private?Phone[]?phones2; ???????//省略GET和SET... } |
| 1 2 3 | public?class?Phone?{ ???????????????private?String?brand;//手機品牌 } |
Controller方法如下
| 1 2 3 4 5 6 7 8 9 10 | /** *?綁定數據到User對象,支持Map,Set,List,Array等,但是需要使用下標,不是很靈活 *?請查看user2的寫法 *?@param?user *?@param?map */ @RequestMapping(value="user") public?void?user(User?user,ModelMap?map){ ???????map.addAttribute("user",?user); } |
HTML表單如下
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <form?action="request/user"?method="get"?style="border:1px?solid?red;"> ?????<table> ???????????<tr><td?colspan="2">這個表單演示了對象數據綁定的方法,以及對象中的Set,List,Array數據綁定(三者類似)</td></tr> ????????????<tr> ????????????????<td>用戶名:</td> ????????????????<td><input?type="text"?name="userName"?value="張三"></td> ????????????</tr> ????????????<tr> ????????????????<td>用戶地址:</td> ????????????????<td><input?type="text"?name="address"?value="江蘇省無錫市新區菱湖大道200號"><br></td> ????????????</tr> ????????????<tr> ????????????????<td>手機品牌:</td> ????????????????<td> ????????????????????<input?type="text"?name="phones[0].brand"?value="SONY"><br> ????????????????????<input?type="text"?name="phones[1].brand"?value="MOTO"><br> ????????????????????<input?type="text"?name="phones[2].brand"?value="LG"><br> ?????????????????</td> ?????????????</tr> ?????????????<tr> ?????????????????<td>手機品牌2:</td> ?????????????????<td> ?????????????????????<input?type="text"?name="phones2[0].brand"?value="Apple"><br> ?????????????????????<input?type="text"?name="phones2[1].brand"?value="Samsung"><br> ?????????????????????<input?type="text"?name="phones2[2].brand"?value="HTC"><br> ?????????????????</td> ??????????????</tr> ??????????????<tr> ??????????????????<td?colspan="2"?style="text-align:?right;"> ??????????????????<input?type="submit"?value="提交"> ??????????????????</td> ???????????????</tr> ???????</table> </form> |
一對多的時候,使用多一方的在一一方的對象中的屬性名,加上數組下標,即phones[0].brand,phones[1].brand即可綁定到User的phones屬性上,這種方法的局限性就是要求下標是正確的,否則會無法綁定,不是很方便,但是也有其適用場景。
下面這種方法就是比較方便了,僅支持post,但是必須要在消息轉換器中配置JSON解析器
| 1 | <bean?class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean> |
并注冊到RequestMappingHandlerAdapter的messageConverters中。
Controller如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | /** ?*?這里可以接受List,Array,Set等,寫法是一樣的,注意前端寫法<br> ?*?另外這個必須要使用MappingJacksonHttpMessageConverter這個消息轉換器 ?*?請看我上面的配置 ?*?@param?user ?*?@return ?*/ ?@ResponseBody ?@RequestMapping("user2") ?public?String?user2(@RequestBody?List<User>?user){ ?????????System.out.println(user.size()); ?????????return?""; ?} |
Javascript如下
| 1 2 3 4 5 6 7 8 9 10 11 12 13 | var?userList=?new?Array(); userList.push({userName:"xx",address:"fff"}); userList.push({userName:"zzzz",address:"ggggg"}); $.ajax({ ??url:"request/user2", ??type:"post", ??data:JSON.stringify(userList), ??dataType:"json", ??contentType:"application/json", ??success:function(data){ ???},error:function(data){ ??} }); |
該方法僅支持POST的方式,會使用到json2.js這個類庫,注意設置contentType:"application/json"這個屬性,否則會報415未知的類型異常。
傳遞簡單的字符串數組,僅支持POST方式
| 1 2 3 4 5 6 7 8 9 10 11 12 | /** *?傳遞簡單的字符串數組 *?這個方法只支持POST *?@param?s *?@return */ @ResponseBody @RequestMapping("array") public?String?array(@RequestBody?String[]?s){ ????System.out.println(s.length); ????return?""; ?} |
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | var?array=new?Array(); array.push(1); array.push(2); array.push(3); array.push(4); array.push(5); $.ajax({ ????url:"request/array", ????type:"post", ????dataType:"json", ????data:JSON.stringify(array), ????dataType:"json", ????contentType:"application/json", ????success:function(data){ ????},error:function(data){ ????} }); |
和上面的方法類似,注意contentType:"application/json",否則同樣的415錯誤。
下面的方法是restful中的路徑變量,支持get,post,delete等,如:xxx/1,xxx/2這種方式,經測試,這個方法的奇葩之處在于"xxx/5,4"以及"xxx/[5,4]"的效果是一樣的,看代碼:
| 1 2 3 4 5 6 7 8 9 10 11 | /** *?這個比較奇葩,來自一位朋友的寫法,即.xxx/5,4這樣的請求,SpringMVC竟然也是支持的 *?@param?id *?@return */ @ResponseBody @RequestMapping(value="array/{id}",method=RequestMethod.GET) public?String?array2(@PathVariable("id")Long[]?id){ ???????System.out.println(id.length); ???????return?"array?length:"+id.length+""; } |
可以直接將后面的路徑變量,轉換成相應的數組。可以在瀏覽器輸入:http://localhost:8080/springmvc-param/request/array/5,4,3,2,1或者http://localhost:8080/springmvc-param/request/array/[5,4,3,2,1],都可以轉換成數組。
如果一個表單對應多個實體類,恰好這些類中具有相同的屬性,這時候SpringMVC就犯難了,我們要做的是讓SpringMVC明白我們在給誰賦值。
支持post,get,put
如下,A,B,C,其中C中包含了A和B兩個成員變量
| 1 2 3 | public?class?A?{ ???????private?String?x; } |
| 1 2 3 | public?class?B?{ ???????private?String?x; } |
| 1 2 3 4 | public?class?C?{ ???????private?A?a; ???????private?B?b; } |
Controller如下
| 1 2 3 4 5 6 7 8 9 10 11 | /** *?一個表單對應多個Bean對象,這些Bean中有相同的屬性,那么需要在分裝他們的一個整體的對象 *?使之支持object.property的表達式 *?@param?c */ @ResponseBody @RequestMapping("complex") public?void?complexObject(C?c){ ???????System.out.println(c.getA().getX()); ???????System.out.println(c.getB().getX()); } |
HTML如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <form?action="request/complex"?method="POST"?style="border:1px?solid?red;"> ??????<table> ?????????????<tr> ?????????????????<td>A對象:</td> ?????????????????<td><input?type="text"?name="a.x"?value="xxx"></td> ??????????????</tr> ??????????????<tr> ??????????????????<td>B對象:</td> ??????????????????<td><input?type="text"?name="b.x"?value="yyy"><br></td> ??????????????</tr> ??????????????<tr> ??????????????????<td?colspan="2"?style="text-align:?right;"> ?????????????????????<input?type="submit"?value="提交"> ??????????????????</td> ??????????????</tr> ????????</table> </form> |
通過object.property即可指定給誰賦值。
另外一個是關于Session取值的
代碼如下
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @Controller @SessionAttributes(value="user") @RequestMapping("/session") public?class?SessionController?{ ????@RequestMapping(method=RequestMethod.GET)????? ????public?String?setUser(ModelMap?map){? ????????User?user=new?User();? ????????user.setAddress("xxx");? ????????user.setUserName("yyy"); ????????map.put("user",?user); ????????return?"request/userForm"; ????} ???????????????? ????@ResponseBody ????@RequestMapping(value="getUser",method=RequestMethod.GET) ????public?String?getUser(@ModelAttribute("user")User?user){ ???????????System.out.println(user.getUserName()); ???????????return?user.getUserName(); ????} } |
在Controller上加上注解@SessionAttributes(value="user"),再使用ModelMap的put方法(非addAttribute方法),然后在getUser方法中,使用@ModelAttribute("user")即可取得session中的user對象
Maven依賴:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <properties> ????????????<springframework>4.0.5.RELEASE</springframework> ????????????<servlet>3.1.0</servlet> ????????????<jstl>1.2</jstl> ????????????<xstream>1.4.7</xstream> ????????????<commons-fileupload>1.3.1</commons-fileupload> ????????????<jackson>1.9.13</jackson> </properties> <dependencies> ????????????<!--?jackson?json解析支持?--> ????????????<dependency> ????????????????????????<groupId>org.codehaus.jackson</groupId> ????????????????????????<artifactId>jackson-mapper-asl</artifactId> ????????????????????????<version>${jackson}</version> ????????????</dependency> ????????????<!--?Spring?web?mvc?--> ????????????<dependency> ????????????????????????<groupId>org.springframework</groupId> ????????????????????????<artifactId>spring-webmvc</artifactId> ????????????????????????<version>${springframework}</version> ????????????</dependency> ????????????<!--?servlet?--> ????????????<dependency> ????????????????????????<groupId>javax.servlet</groupId> ????????????????????????<artifactId>javax.servlet-api</artifactId> ????????????????????????<version>${servlet}</version> ????????????</dependency> ????????????<!--?JSTL?--> ????????????<dependency> ????????????????????????<groupId>jstl</groupId> ????????????????????????<artifactId>jstl</artifactId> ????????????????????????<version>${jstl}</version> ????????????</dependency> ????????????<!--xml解析支持?--> ????????????<dependency> ????????????????????????<groupId>com.thoughtworks.xstream</groupId> ????????????????????????<artifactId>xstream</artifactId> ????????????????????????<version>${xstream}</version> ????????????</dependency> </dependencies> |
Spring配置
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | @EnableWebMvc//?啟用SpringMVC @ComponentScan(basePackages?=?"org.xdemo.example.springmvc")//?配置包掃描路徑 @Configuration//?啟用注解式配置 //繼承WebMvcConfigurerAdapter可以是我們可以重寫一些資源或者一些處理器 public?class?AppConfig?extends?WebMvcConfigurerAdapter?{ ???????????????/** ????????????????*?設置資源路徑 ????????????????*/ ???????????????@Override ???????????????public?void?addResourceHandlers(ResourceHandlerRegistry?registry)?{ ??????????????????????registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(31556926); ???????????????} ???????????????/** ????????????????*?設置默認的Servlet請求處理器 ????????????????*/ ???????????????@Override ???????????????public?void?configureDefaultServletHandling(DefaultServletHandlerConfigurer?configurer)?{ ??????????????????????configurer.enable(); ???????????????} ???????????????/** ????????????????*?設置視圖解析器,以及頁面路徑 ????????????????*? ????????????????*?@return ????????????????*/ ???????????????@Bean ???????????????public?InternalResourceViewResolver?getInternalResourceViewResolver()?{ ???????????????????????????????InternalResourceViewResolver?resolver?=?new?InternalResourceViewResolver(); ???????????????????????????????resolver.setPrefix("/WEB-INF/views/"); ???????????????????????????????resolver.setSuffix(".jsp"); ???????????????????????????????return?resolver; ???????????????} ???????????????? ???????????????/** ????????????????*?配置消息轉換器 ????????????????*/ ???????????????@Override ???????????????public?void?configureMessageConverters( ??????????????????????List<HttpMessageConverter<?>>?converters)?{converters.add(converter()); ???????????????????????????????? ???????????????} ???????????????? ???????????????/** ????????????????*?JSON格式的支持,這個很重要,只有加上這個JSON的消息轉換器,才能夠支持JSON格式數據的綁定 ????????????????*?@return ????????????????*/ ???????????????@Bean ???????????????public?MappingJacksonHttpMessageConverter?converter()?{ ??????????????????????????????MappingJacksonHttpMessageConverter?converter?=?new?MappingJacksonHttpMessageConverter(); ???????????????????????????????return?converter; ???????????????} } |
轉載請注明來源:http://www.xdemo.org/springmvc-data-bind/
總結
以上是生活随笔為你收集整理的SpringMVC数据绑定全面示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是代码中的魔鬼数字,如何解决?
- 下一篇: android-加固方案对比