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í)使用,但兩者的值需一致,否則會出現(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類型,并不會做其他處理。因此若需要向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返回類型方法,會自動將返回值添加到ModelMap中,鍵根據(jù)返回類型生成.";
}
③ @ModelAttribute注釋非void返回類型方法,并指定其name或value屬性
?此種情況下,①中所使用操作ModelMap方式仍然有效,需要通過方法參數(shù)ModelMap來添加屬性。
同時(shí),以@ModelAttribute注解name或value屬性值、返回值作為鍵值對添加到ModelMap中。
@ModelAttribute("defModelAttributeName")
public String modelAttributeWithStringMethodDefName(ModelMap modelMap) {
return "@ModelAttribute注釋String類型返回值方法,會自動將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.";
}
④ @ModelAttribute與@RequestMapping注釋同一方法
此種情況下,@ModelAttribute與@RequestMapping相互作用,會使@RequestMapping表現(xiàn)出稍許差異。@ModelAttribute會使得@RequestMapping注釋方法的某些類型返回值不會使用對應(yīng)HandlerMethodReturnValueHandler,而是由ModelAttributeMethodProcessor解析。
ModelAttributeMethodProcessor會針對返回值與②或③中進(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類型返回值方法.
* 需要手動ModelMap中添加數(shù)據(jù).
*/
@ModelAttribute
public void modelAttributeWithVoidMethod(ModelMap modelMap) {
modelMap.addAttribute("modelAttributeWithVoidMethod",
"@ModelAttribute注釋在void返回類型的方法上.");
}
/**
* @ModelAttribute注釋
* String返回類型方法.
* 會自動將返回值添加到ModelMap中,鍵根據(jù)返回類型生成.
*/
@ModelAttribute
public String modelAttributeWithStringMethod() {
return "@ModelAttribute注釋String返回類型方法,會自動將返回值添加到ModelMap中,鍵根據(jù)返回類型生成.";
}
/**
* @ModelAttribute注釋
* String類型返回值方法.
* 會自動將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.
*/
@ModelAttribute("defModelAttributeName")
public String modelAttributeWithStringMethodDefName() {
return "@ModelAttribute注釋String類型返回值方法,會自動將返回值添加到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) 啟動服務(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類型返回值方法,會自動將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.",
"string":"@ModelAttribute注釋String返回類型方法,會自動將返回值添加到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類型返回值方法,會自動將返回值添加到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類型返回值方法,會自動將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.",
"modelAttributeWithVoidMethod":"@ModelAttribute注釋在void返回類型的方法上.",
"string":"@ModelAttribute注釋String返回類型方法,會自動將返回值添加到ModelMap中,鍵根據(jù)返回類型生成."
}
2020-12-16 16:31:41 INFO [c.a.s.w.ModelAttributeController] @ModelAttribute注釋方法參數(shù),從ModelMap中取值:[key=defModelAttributeName, value=@ModelAttribute注釋String類型返回值方法,會自動將返回值添加到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)文章
解決SpringMVC項(xiàng)目連接RabbitMQ出錯(cuò)的問題
這篇文章主要介紹了解決SpringMVC項(xiàng)目連接RabbitMQ出錯(cuò)的問題,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-01-01
任何Bean通過實(shí)現(xiàn)ProxyableBeanAccessor接口即可獲得動態(tài)靈活的獲取代理對象或原生對象的能力(最新推
這篇文章主要介紹了任何Bean通過實(shí)現(xiàn)ProxyableBeanAccessor接口即可獲得動態(tài)靈活的獲取代理對象或原生對象的能力,通過示例代碼看到,借助ProxyableBeanAccessor接口默認(rèn)實(shí)現(xiàn)的getReal、getProxy、selfAs方法,很靈活的按需獲取代理或非代理對象,需要的朋友可以參考下2024-02-02
使用JAVA8 filter對List多條件篩選的實(shí)現(xiàn)
這篇文章主要介紹了使用JAVA8 filter對List多條件篩選的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
java本服務(wù)如何調(diào)用本服務(wù)接口
這篇文章主要介紹了java本服務(wù)如何調(diào)用本服務(wù)接口問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
如何解決使用restTemplate進(jìn)行feign調(diào)用new HttpEntity<>報(bào)錯(cuò)問題
這篇文章主要介紹了如何解決使用restTemplate進(jìn)行feign調(diào)用new HttpEntity<>報(bào)錯(cuò)問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Java異常:java.net.UnknownHostException產(chǎn)生的原因和解決方案
這篇文章主要給大家介紹了關(guān)于Java異常:java.net.UnknownHostException產(chǎn)生的原因和解決方案,這個(gè)異常是java.net包中的一部分,具體說它是類的一個(gè)實(shí)例,異常通常是由主機(jī)名無法解析為IP地址引起的,文中將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01

