SpringMVC中參數(shù)綁定問(wèn)題實(shí)例詳解
前言
眾所周知,springmvc是用來(lái)處理頁(yè)面的一些請(qǐng)求,然后將數(shù)據(jù)再通過(guò)視圖返回給用戶(hù)的,前面的幾篇博文中使用的都是靜態(tài)數(shù)據(jù),為了能快速入門(mén)springmvc,在這一篇博文中,我將總結(jié)一下springmvc中如何接收前臺(tái)頁(yè)面的參數(shù),即springmvc中的參數(shù)綁定問(wèn)題。
1. 參數(shù)綁定的過(guò)程
我們可以回憶一下,在struts2中,是通過(guò)在Action中定義一個(gè)成員變量來(lái)接收前臺(tái)傳進(jìn)來(lái)的參數(shù),而在springmvc中,接收頁(yè)面提交的數(shù)據(jù)是通過(guò)方法形參來(lái)接收的。從客戶(hù)端請(qǐng)求的key/value數(shù)據(jù),經(jīng)過(guò)參數(shù)綁定,將key/value數(shù)據(jù)綁定到controller方法的形參上,然后就可以在controller中使用該參數(shù)了。來(lái)看一下這個(gè)過(guò)程:
所以我們知道,是springmvc提供了很多轉(zhuǎn)換器來(lái)將頁(yè)面參數(shù)綁定到controller方法的形參上,關(guān)于自定義converter,我下面會(huì)提到。大概了解了該過(guò)程后,下面開(kāi)始做具體的總結(jié)。
2. 默認(rèn)支持的類(lèi)型
springmvc中,有支持的默認(rèn)類(lèi)型的綁定。也就是說(shuō),直接在controller方法形參上定義默認(rèn)類(lèi)型的對(duì)象,就可以使用這些對(duì)象。
HttpServletRequest對(duì)象HttpServletResponse對(duì)象HttpSession對(duì)象Model/ModelMap對(duì)象
在參數(shù)綁定過(guò)程中,如果遇到上面類(lèi)型就直接進(jìn)行綁定。也就是說(shuō),我們可以在controller的方法的形參中直接定義上面這些類(lèi)型的參數(shù),springmvc會(huì)自動(dòng)綁定。這里要說(shuō)明一下的就是Model/ModelMap對(duì)象,Model是一個(gè)接口,ModelMap是一個(gè)接口實(shí)現(xiàn) ,作用是將Model數(shù)據(jù)填充到request域,跟ModelAndView類(lèi)似,關(guān)于它的使用,我在下面和簡(jiǎn)單類(lèi)型參數(shù)綁定一起說(shuō)。
3. 簡(jiǎn)單類(lèi)型的綁定
總結(jié)這個(gè)還是以需求為例吧,這樣比較容易理解,假設(shè)現(xiàn)在有個(gè)需求:根據(jù)商品的id來(lái)修改對(duì)應(yīng)點(diǎn)商品信息。所以前臺(tái)頁(yè)面肯定要傳進(jìn)來(lái)該商品的id,然后springmvc的controller進(jìn)行處理,返回一個(gè)修改商品信息的頁(yè)面。關(guān)于前臺(tái)頁(yè)面的東西都很簡(jiǎn)單,我就不貼代碼了,主要部分截個(gè)圖,具體的代碼在文章最后有下載地址。
前臺(tái)頁(yè)面通過(guò)url將參數(shù)傳遞過(guò)來(lái),請(qǐng)求的是editItems.action。
下面寫(xiě)controller中的editItems方法:
@RequestMapping("/editItems") public String editItems(Model model, Integer id) throws Exception { //根據(jù)id查詢(xún)對(duì)應(yīng)的Items ItemsCustom itemsCustom = itemsService.findItemsById(id); model.addAttribute("itemsCustom", itemsCustom); //通過(guò)形參中的model將model數(shù)據(jù)傳到頁(yè)面 //相當(dāng)于modelAndView.addObject方法 return "/WEB-INF/jsp/items/editItems.jsp"; }
這是個(gè)很簡(jiǎn)單的demo,從上面的代碼中可以看出model可以直接作為參數(shù),springmvc默認(rèn)會(huì)綁定它,然后使用model將查詢(xún)到的數(shù)據(jù)放到request域中,這樣就可以在前臺(tái)頁(yè)面取出該數(shù)據(jù)了。
要注意一點(diǎn)的是,簡(jiǎn)單類(lèi)型的綁定中,方法形參中的參數(shù)名要和前臺(tái)傳進(jìn)來(lái)的名一樣才能完成參數(shù)的綁定。那有人要問(wèn)了,如果有特殊需求(比如更好的可讀性?),這里定義的參數(shù)名就是不一樣,那咋整呢?有解決辦法么?有!我們可以使用注解@RequestParam對(duì)簡(jiǎn)單的類(lèi)型進(jìn)行參數(shù)綁定,如下:
所以說(shuō),如果不使用@RequestParam,要求request傳入?yún)?shù)名稱(chēng)和controller方法的形參名稱(chēng)一致,方可綁定成功。如果使用@RequestParam,不用限制request傳入?yún)?shù)名稱(chēng)和controller方法的形參名稱(chēng)一致。通過(guò)@RequestParam中的required屬性指定參數(shù)是否必須要傳入,如果設(shè)置為true,沒(méi)有傳入?yún)?shù)就會(huì)報(bào)錯(cuò)。
4. pojo類(lèi)型的綁定
4.1 普通pojo類(lèi)型
再來(lái)總結(jié)下pojo類(lèi)型的綁定,繼續(xù)上面的案例,當(dāng)頁(yè)面展示了商品詳細(xì)信息后,我做了修改,然后點(diǎn)擊提交,后臺(tái)應(yīng)該將我提交的這些參數(shù)全部更新到數(shù)據(jù)庫(kù)的items表中,也就是說(shuō),我提交的這些參數(shù)要綁定到Items對(duì)象或者其擴(kuò)展對(duì)象中。先看一下Items中都有哪些屬性:
可以看到,有各種類(lèi)型的屬性,當(dāng)我們提交后,要將這些屬性全部封裝到一個(gè)pojo中,然后去更新數(shù)據(jù)庫(kù)。
綁定很簡(jiǎn)單,對(duì)于基本類(lèi)型,要求頁(yè)面中input標(biāo)簽的name屬性值和controller的pojo形參中的屬性名稱(chēng)一致,即可將頁(yè)面中數(shù)據(jù)綁定到pojo。也就是說(shuō)前臺(tái)頁(yè)面?zhèn)鬟M(jìn)來(lái)的name要和要封裝的pojo屬性名一模一樣,然后就可以將該pojo作為形參放到controller的方法中,如下:
這樣就能將前臺(tái)表單傳進(jìn)來(lái)的不同屬性值封裝到ItemsCustom中了。但是運(yùn)行一下就會(huì)發(fā)現(xiàn)報(bào)錯(cuò),報(bào)錯(cuò)的信息是無(wú)法將String類(lèi)型轉(zhuǎn)換成java.util.Date類(lèi)型,因?yàn)樯厦鍵tems中有一個(gè)屬性是Date類(lèi)型的createtime。這就需要我們自己定義轉(zhuǎn)換器了,這也是這部分的重點(diǎn),下面我們自己定義一個(gè)日期轉(zhuǎn)換器:
//需要實(shí)現(xiàn)Converter接口,這里是將String類(lèi)型轉(zhuǎn)換成Date類(lèi)型 public class CustomDateConverter implements Converter<String, Date> { @Override public Date convert(String source) { //實(shí)現(xiàn) 將日期串轉(zhuǎn)成日期類(lèi)型(格式是yyyy-MM-dd HH:mm:ss) SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { //轉(zhuǎn)成直接返回 return simpleDateFormat.parse(source); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } //如果參數(shù)綁定失敗返回null return null; } }
定義好了轉(zhuǎn)換器后,需要在springmvc.xml中進(jìn)行如下配置:
現(xiàn)在就可以了,springmvc就能根據(jù)這個(gè)轉(zhuǎn)換器將String類(lèi)型正確轉(zhuǎn)換成Date類(lèi)型,然后封裝到ItemsCustom中去了。
這里說(shuō)一個(gè)小小的插曲:修改商品詳細(xì)信息后提交,可能會(huì)有中文亂碼問(wèn)題,表達(dá)提交都是post方式,springmvc中關(guān)于post方式的中文亂碼問(wèn)題可以在web.xml中配置一個(gè)過(guò)濾器來(lái)解決,如下:
4.2. 包裝的pojo類(lèi)型
這個(gè)包裝類(lèi)型pojo與上面普通的pojo有啥區(qū)別呢?包裝類(lèi)型pojo指的是pojo中有另一個(gè)也是pojo的屬性,即pojo套pojo,為什么會(huì)設(shè)計(jì)這種pojo呢?在前面的博文中我也有提到,這種組合的設(shè)計(jì)方法對(duì)于后期程序的擴(kuò)展很有用,比如復(fù)雜的查詢(xún)條件就需要包裝到這種包裝類(lèi)型中。
那么該如何綁定呢?有兩個(gè)思路:
在形參中添加HttpServletRequest request參數(shù),通過(guò)request接收查詢(xún)條件參數(shù)。在形參中讓包裝類(lèi)型的pojo接收查詢(xún)條件參數(shù)。
第一種方式就跟原始servlet差不多,這里使用第二種方法,我們傳進(jìn)來(lái)一個(gè)包裝類(lèi)型的pojo??匆幌逻@個(gè)包裝類(lèi)型的pojo:
這個(gè)包裝pojo中還有一個(gè)ItemsCustom類(lèi),這個(gè)類(lèi)繼承了Items類(lèi),并且用來(lái)擴(kuò)展與Items相關(guān)的User對(duì)象中的相關(guān)信息。所以這個(gè)ItemsCustom中有name屬性,假如我們要想將前臺(tái)傳進(jìn)來(lái)的name屬性封裝到ItemsCustom中的name屬性中,該如何傳入呢?這就是包裝類(lèi)型的pojo參數(shù)綁定問(wèn)題。
很簡(jiǎn)單,在前臺(tái)我們可以通過(guò)這種方式來(lái)傳:
然后controller中方法的形參傳入包裝類(lèi)型的pojo,即ItemsQueryVo,打個(gè)斷點(diǎn),即可查看值有沒(méi)有傳進(jìn)來(lái)。如下:
這樣就能根據(jù)用戶(hù)傳進(jìn)來(lái)的參數(shù),進(jìn)行復(fù)制的查詢(xún)操作了。
5. 集合類(lèi)型的綁定
5.1 數(shù)組的綁定
數(shù)組的綁定指的是前臺(tái)傳來(lái)多個(gè)同一類(lèi)型的數(shù)據(jù),我們?cè)赾ontroller中使用數(shù)組形參來(lái)接收前臺(tái)傳來(lái)的數(shù)據(jù)。還是以案例來(lái)驅(qū)動(dòng)這部分內(nèi)容,比如現(xiàn)在我們要批量刪除商品,那么我們需要勾選好幾個(gè)商品,這些商品都有id號(hào),在controller中,我們需要將這些id號(hào)全部獲取并放到一個(gè)數(shù)組中,然后再根據(jù)數(shù)組中的id號(hào)挨個(gè)刪除數(shù)據(jù)庫(kù)中對(duì)應(yīng)的項(xiàng)。那么該如何綁定呢?其實(shí)也很簡(jiǎn)單,如下:
controller的方法定義為:
對(duì)應(yīng)前臺(tái)傳入的參數(shù)為:
這樣就能將前臺(tái)傳入的多個(gè)id綁定到數(shù)組中,然后我們就可以從數(shù)組中拿出要?jiǎng)h除的商品的id了。
5.2 List的綁定
通常在需要批量提交數(shù)據(jù)時(shí),將提交的數(shù)據(jù)綁定到list<pojo>
中,比如:成績(jī)錄入(錄入多門(mén)課成績(jī),批量提交),在這里我們假設(shè)有需求:批量商品修改,在頁(yè)面輸入多個(gè)商品信息,將多個(gè)商品信息提交到controller方法中,即一次性更新多個(gè)商品信息。
所以思路是在擴(kuò)展類(lèi)ItemsQueryVo中新添加一個(gè)List<ItemsCustom>
,然后將不同商品的信息都存到這個(gè)List中,所以修改如下:
controller方法的定義:
1、進(jìn)入批量商品修改頁(yè)面
2、批量修改商品提交
所以controller中應(yīng)該有兩個(gè)方法,如下:
前臺(tái)jsp頁(yè)面中是如何傳入?yún)?shù)的呢?這是我們所關(guān)心的問(wèn)題,因?yàn)楹笈_(tái)形參中接收數(shù)據(jù)用的就是包裝類(lèi)ItemsQueryVo??聪旅妫?/p>
所以我們知道了,前臺(tái)是通過(guò)類(lèi)似于list[i].name這種形式來(lái)傳遞參數(shù)的。list[i]表示第i個(gè)ItemsCustom,然后 list[i].屬性 表示第i個(gè)ItemsCustom中對(duì)應(yīng)的屬性。
5.2 Map的綁定
Map的綁定其實(shí)和List的綁定是差不多的,首先也是在包裝的pojo中新添加一個(gè)Map類(lèi)型的屬性,如(我隨便舉個(gè)例子,跟本例無(wú)關(guān)了)
Public class QueryVo { private Map<String, Student> itemInfo = new HashMap<String, Student>(); //get/set方法.. }
關(guān)鍵是前臺(tái)傳參的時(shí)候和List不太一樣,Map是這樣傳的,比如:
<tr> <td>學(xué)生信息:</td> <td> 姓名:<input type="text" name="itemInfo['name']"/> 年齡:<input type="text" name="itemInfo['price']"/> .. .. .. </td> </tr>
我們可以看到,Map的參數(shù)綁定傳來(lái)的是Map中的key,然后value會(huì)自動(dòng)綁定到Map中的那個(gè)對(duì)象的屬性中。在controller中的方法里,形參就直接使用QueryVo接收即可,也很簡(jiǎn)單。
關(guān)于springmvc的參數(shù)綁定基本就總結(jié)到這了,其實(shí)原理都差不多,只是針對(duì)于不同的類(lèi)型,綁定的方式有些區(qū)別而已,多想想多寫(xiě)寫(xiě),基本就能掌握這些了。
學(xué)習(xí)筆記源碼下載地址:https://github.com/eson15/SpringMVC_Study
總結(jié)
到此這篇關(guān)于SpringMVC中參數(shù)綁定問(wèn)題的文章就介紹到這了,更多相關(guān)SpringMVC參數(shù)綁定內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JAVA實(shí)現(xiàn)掃描線(xiàn)算法(超詳細(xì))
掃描線(xiàn)算法就是從Ymin開(kāi)始掃描,然后構(gòu)建出NET,之后根據(jù)NET建立AET。接下來(lái)本文通過(guò)代碼給大家介紹JAVA實(shí)現(xiàn)掃描線(xiàn)算法,感興趣的朋友一起看看吧2019-10-10Java面試題沖刺第二十八天--數(shù)據(jù)庫(kù)(5)
這篇文章主要為大家分享了最有價(jià)值的三道關(guān)于數(shù)據(jù)庫(kù)的面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結(jié)構(gòu)和算法相關(guān)的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下2021-09-09Jedis出現(xiàn)connection timeout問(wèn)題解決方法(JedisPool連接池使用實(shí)例)
這篇文章主要介紹了Jedis出現(xiàn)connection timeout問(wèn)題解決方法,使用Jedis的JedisPool連接池解決了這個(gè)問(wèn)題,需要的朋友可以參考下2014-05-05java 中JFinal getModel方法和數(shù)據(jù)庫(kù)使用出現(xiàn)問(wèn)題解決辦法
這篇文章主要介紹了java 中JFinal getModel方法和數(shù)據(jù)庫(kù)使用出現(xiàn)問(wèn)題解決辦法的相關(guān)資料,需要的朋友可以參考下2017-04-04springboot整合mybatis-plus基于注解實(shí)現(xiàn)一對(duì)一(一對(duì)多)查詢(xún)功能
這篇文章主要介紹了springboot整合mybatis-plus基于純注解實(shí)現(xiàn)一對(duì)一(一對(duì)多)查詢(xún)功能,因?yàn)楸救瞬捎玫氖莝pring-boot進(jìn)行開(kāi)發(fā),本身springboot就提倡采用不用配置自動(dòng)配置的方式,所以真心希望mybatis(不是mybatis-plus)這點(diǎn)需要繼續(xù)努力2021-09-09SpringMVC上傳文件的三種實(shí)現(xiàn)方式
本篇文章主要介紹了SpringMVC上傳文件的三種實(shí)現(xiàn)方式,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12