Spring中的@ModelAttribute模型屬性綁定詳解
前言
@ModelAttribute用于將方法參數(shù)或返回值綁定到Model屬性上,并公開給Web視圖。
支持使用@RequestMapping注釋的Controller類。
注解解析
① value:
待綁定到Model屬性的鍵名稱。
默認(rèn)Model屬性鍵名稱根據(jù)非限定類名從聲明的屬性類型(即方法參數(shù)類型或方法返回類型)推斷而來:
mypackage.OrderAddress類型對應(yīng)的鍵名稱是orderAddress 。
List<mypackage.OrderAddress>類型對應(yīng)的鍵名稱是orderAddressList。
② name:
綁定的參數(shù)名稱,參數(shù)值為String類型。name和value可以同時(shí)使用,但兩者的值需一致,否則會(huì)出現(xiàn)錯(cuò)誤。
attribute 'name' and its alias 'value' are present with values of [XXX] and [XXX], but only one is permitted
③ binding:
允許直接在@ModelAttribute注釋的方法參數(shù)或@ModelAttribute注釋的方法返回值上聲明禁用數(shù)據(jù)綁定,這兩種方法都將阻止數(shù)據(jù)綁定。
默認(rèn)情況下,binding被設(shè)置為true,此時(shí)將正常進(jìn)行數(shù)據(jù)綁定。將binding設(shè)置為false,將禁用數(shù)據(jù)綁定。
注解應(yīng)用
1) @ModelAttribute注釋方法
@ModelAttribute注釋方法將在Controller中@RequestMapping注釋方法前被調(diào)用。對于@ModelAttribute注釋方法有以下幾種情況:
① @ModelAttribute注釋void返回類型方法
此種情況下,由于方法返回值為void類型,并不會(huì)做其他處理。因此若需要向ModeMap中添加屬性,需要通過方法參數(shù)ModelMap來完成。
@ModelAttribute public void modelAttributeWithVoidMethod(ModelMap modelMap) { modelMap.addAttribute("modelAttributeWithVoidMethod", "@ModelAttribute注釋在void返回類型的方法上."); }
② @ModelAttribute注釋非void返回類型方法
此種情況下,①中所使用操作ModelMap方式仍然有效,需要通過方法參數(shù)ModelMap來添加屬性。
同時(shí),以返回值類型推斷出的鍵、返回值作為鍵值對添加到ModelMap中。
@ModelAttribute public String modelAttributeWithStringMethod() { return "@ModelAttribute注釋String返回類型方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵根據(jù)返回類型生成."; }
③ @ModelAttribute注釋非void返回類型方法,并指定其name或value屬性
?此種情況下,①中所使用操作ModelMap方式仍然有效,需要通過方法參數(shù)ModelMap來添加屬性。
同時(shí),以@ModelAttribute注解name或value屬性值、返回值作為鍵值對添加到ModelMap中。
@ModelAttribute("defModelAttributeName") public String modelAttributeWithStringMethodDefName(ModelMap modelMap) { return "@ModelAttribute注釋String類型返回值方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值."; }
④ @ModelAttribute與@RequestMapping注釋同一方法
此種情況下,@ModelAttribute與@RequestMapping相互作用,會(huì)使@RequestMapping表現(xiàn)出稍許差異。@ModelAttribute會(huì)使得@RequestMapping注釋方法的某些類型返回值不會(huì)使用對應(yīng)HandlerMethodReturnValueHandler,而是由ModelAttributeMethodProcessor解析。
ModelAttributeMethodProcessor會(huì)針對返回值與②或③中進(jìn)行同樣處理。視圖名稱由RequestToViewNameTranslator根據(jù)請求/ModelAttributeWithRequestMapping.do轉(zhuǎn)換為邏輯視圖ModelAttributeWithRequestMapping。
不受影響的返回類型包括:ModelAndView、 Model、 View、ResponseBodyEmitter、StreamingResponseBody、HttpEntity、HttpHeaders、Callable、DeferredResult、AsyncTask。
@ModelAttribute @RequestMapping( value = "/ModelAttributeWithRequestMapping.do", method = RequestMethod.GET) public String modelAttributeWithRequestMapping(ModelMap modelMap) throws Exception { logger.info("@ModelAttribute與@RequestMapping共同作用在一個(gè)方法."); return "webannotations/ModelAttribute"; }
2) @ModelAttribute注釋參數(shù)
① @ModelAttribute注釋方法參數(shù)
此種情況下,@ModelAttribute注解用于ModelMap數(shù)據(jù)映射到控制器處理方法的參數(shù)中。
@RequestMapping( value = "/ModelAttributeParameters.do", method = RequestMethod.GET) public ModelAndView modelAttributeParameters(@ModelAttribute("defModelAttributeName") String modelAttr, ModelMap modelMap) throws Exception { logger.info("@ModelAttribute注釋方法參數(shù),從ModelMap中取值:[key=defModelAttributeName, value=" + modelAttr + "]."); return new ModelAndView("webannotations/ModelAttribute", modelMap); }
注解示例
1) 建Controller,用來演示@ModelAttribute使用方法。
package com.arhorchin.securitit.webannotations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; /** * @author Securitit. * @note 演示@ModelAttribute使用方法. */ @Controller @RequestMapping("/WebAnnotations") public class ModelAttributeController { /** * logger. */ private Logger logger = LoggerFactory.getLogger(ModelAttributeController.class); /** * @ModelAttribute注釋 * void類型返回值方法. * 需要手動(dòng)ModelMap中添加數(shù)據(jù). */ @ModelAttribute public void modelAttributeWithVoidMethod(ModelMap modelMap) { modelMap.addAttribute("modelAttributeWithVoidMethod", "@ModelAttribute注釋在void返回類型的方法上."); } /** * @ModelAttribute注釋 * String返回類型方法. * 會(huì)自動(dòng)將返回值添加到ModelMap中,鍵根據(jù)返回類型生成. */ @ModelAttribute public String modelAttributeWithStringMethod() { return "@ModelAttribute注釋String返回類型方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵根據(jù)返回類型生成."; } /** * @ModelAttribute注釋 * String類型返回值方法. * 會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值. */ @ModelAttribute("defModelAttributeName") public String modelAttributeWithStringMethodDefName() { return "@ModelAttribute注釋String類型返回值方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值."; } /** * ModelAttribute.do. */ @RequestMapping( value = "/ModelAttribute.do", method = RequestMethod.GET) public ModelAndView modelAttribute(ModelMap modelMap) throws Exception { logger.info("@ModelAttribute注解測試."); return new ModelAndView("webannotations/ModelAttribute", modelMap); } /** * ModelAttribute.do. * @ModelAttribute與@RequestMapping共同注釋同一方法測試. */ @ModelAttribute @RequestMapping( value = "/ModelAttributeWithRequestMapping.do", method = RequestMethod.GET) public String modelAttributeWithRequestMapping() throws Exception { logger.info("@ModelAttribute與@RequestMapping共同作用在一個(gè)方法."); return "webannotations/ModelAttribute"; } /** * ModelAttributeParameters.do. * @ModelAttribute注釋參數(shù),可以從ModelMap中取指定參數(shù)值. */ @RequestMapping( value = "/ModelAttributeParameters.do", method = RequestMethod.GET) public ModelAndView modelAttributeParameters(@ModelAttribute("defModelAttributeName") String modelAttr, ModelMap modelMap) throws Exception { logger.info("@ModelAttribute注釋方法參數(shù),從ModelMap中取值:[key=defModelAttributeName, value=" + modelAttr + "]."); return new ModelAndView("webannotations/ModelAttribute", modelMap); } }
2) 建ModelAttributeHandlerInterceptor,用來打印演示ModelMap的值。
package com.arhorchin.securitit.interceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.lang.Nullable; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import com.alibaba.fastjson.JSON; /** * @author Securitit. * @note @ModelAttribute查看ModelMap測試. */ public class ModelAttributeHandlerInterceptor implements HandlerInterceptor { /** * logger. */ private Logger logger = LoggerFactory.getLogger(ModelAttributeHandlerInterceptor.class); /** * 在HandlerAdapter實(shí)際調(diào)用處理程序之后調(diào)用,但在DispatcherServlet呈現(xiàn)視圖之前調(diào)用. */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception { logger.info("==============================ModelAttributeHandlerInterceptor postHandle==============================\n" + JSON.toJSONString(modelAndView.getModelMap(), true)); } }
3) 啟動(dòng)服務(wù),訪問//localhost:9199/spring-annotations/WebAnnotations/xxxxx.do,用來查看@ModelAttribute各種使用方法。
① 訪問//localhost:9199/spring-annotations/WebAnnotations/ModelAttribute.do,演示@ModelAttribute注釋單獨(dú)方法。
控制臺輸出:
2020-12-16 16:04:26 INFO [c.a.s.i.ModelAttributeHandlerInterceptor] ==============================ModelAttributeHandlerInterceptor postHandle==============================
{
"defModelAttributeName":"@ModelAttribute注釋String類型返回值方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.",
"string":"@ModelAttribute注釋String返回類型方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵根據(jù)返回類型生成.",
"modelAttributeWithVoidMethod":"@ModelAttribute注釋在void返回類型的方法上."
}
可以看到,@ModelAttribute注釋的modelAttributeWithVoidMethod(...)、modelAttributeWithStringMethod()、modelAttributeWithStringMethodDefName(),按照解析的語義已經(jīng)執(zhí)行。
② 訪問//localhost:9199/spring-annotations/WebAnnotations/ModelAttributeWithRequestMapping.do,演示@ModelAttribute與@RequestMapping共同注釋一個(gè)方法。
控制臺輸出:
2020-12-16 16:11:37 INFO [c.a.s.i.ModelAttributeHandlerInterceptor] ==============================ModelAttributeHandlerInterceptor postHandle==============================
{
"defModelAttributeName":"@ModelAttribute注釋String類型返回值方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.",
"modelAttributeWithVoidMethod":"@ModelAttribute注釋在void返回類型的方法上.",
"string":"webannotations/ModelAttribute"
}
瀏覽器響應(yīng):
除了①中所示語義外,還改變了@RequestMapping注釋方法返回值的語義,將返回值按照規(guī)則添加到ModelMap中,視圖則是由/ModelAttributeWithRequestMapping.do來確定的。
③ 訪問//localhost:9199/spring-annotations/WebAnnotations/ModelAttributeParameters.do,演示@ModelAttribute注釋方法參數(shù)。
2020-12-16 16:31:23 INFO [c.a.s.i.ModelAttributeHandlerInterceptor] ==============================ModelAttributeHandlerInterceptor postHandle==============================
{
"defModelAttributeName":"@ModelAttribute注釋String類型返回值方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.",
"modelAttributeWithVoidMethod":"@ModelAttribute注釋在void返回類型的方法上.",
"string":"@ModelAttribute注釋String返回類型方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵根據(jù)返回類型生成."
}
2020-12-16 16:31:41 INFO [c.a.s.w.ModelAttributeController] @ModelAttribute注釋方法參數(shù),從ModelMap中取值:[key=defModelAttributeName, value=@ModelAttribute注釋String類型返回值方法,會(huì)自動(dòng)將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.].
可以看到,@ModelAttribute注釋方法將從ModelMap中獲取值,綁定到方法參數(shù)上。
總結(jié)
@ModelAttribute主要針對ModelMap進(jìn)行操作,對于傳統(tǒng)的、前后端未分離的應(yīng)用來說,用處還是很大的。
源碼解析基于spring-framework-5.0.5.RELEASE版本源碼。
若文中存在錯(cuò)誤和不足,歡迎指正!
到此這篇關(guān)于Spring中的@ModelAttribute模型屬性綁定詳解的文章就介紹到這了,更多相關(guān)@ModelAttribute模型屬性綁定內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringCloud微服務(wù)調(diào)用丟失請求頭的問題及解決方案
在Spring Cloud 中微服務(wù)之間的調(diào)用會(huì)用到Feign,但是在默認(rèn)情況下,Feign 調(diào)用遠(yuǎn)程服務(wù)存在Header請求頭丟失問題,下面給大家分享SpringCloud微服務(wù)調(diào)用丟失請求頭的問題及解決方案,感興趣的朋友一起看看吧2024-02-02Spring中的@ExceptionHandler異常攔截器
這篇文章主要介紹了Spring中的@ExceptionHandler異常攔截器,Spring的@ExceptionHandler可以用來統(tǒng)一處理方法拋出的異常,給方法加上@ExceptionHandler注解,這個(gè)方法就會(huì)處理類中其他方法拋出的異常,需要的朋友可以參考下2024-01-01詳解spring cloud hystrix請求緩存(request cache)
這篇文章主要介紹了詳解spring cloud hystrix請求緩存(request cache),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05SpringBoot Event實(shí)現(xiàn)異步消費(fèi)機(jī)制的示例代碼
這篇文章主要介紹了SpringBoot Event實(shí)現(xiàn)異步消費(fèi)機(jī)制,ApplicationEvent以及Listener是Spring為我們提供的一個(gè)事件監(jiān)聽、訂閱的實(shí)現(xiàn),內(nèi)部實(shí)現(xiàn)原理是觀察者設(shè)計(jì)模式,文中有詳細(xì)的代碼示例供大家參考,需要的朋友可以參考下2024-04-04Java中StringBuilder字符串類型的操作方法及API整理
Java中的StringBuffer類繼承于AbstractStringBuilder,用來創(chuàng)建非線程安全的字符串類型對象,下面即是對Java中StringBuilder字符串類型的操作方法及API整理2016-05-05