Spring中的@ModelAttribute模型屬性綁定詳解
前言
@ModelAttribute用于將方法參數或返回值綁定到Model屬性上,并公開給Web視圖。
支持使用@RequestMapping注釋的Controller類。
注解解析
① value:
待綁定到Model屬性的鍵名稱。
默認Model屬性鍵名稱根據非限定類名從聲明的屬性類型(即方法參數類型或方法返回類型)推斷而來:
mypackage.OrderAddress類型對應的鍵名稱是orderAddress 。
List<mypackage.OrderAddress>類型對應的鍵名稱是orderAddressList。
② name:
綁定的參數名稱,參數值為String類型。name和value可以同時使用,但兩者的值需一致,否則會出現錯誤。
attribute 'name' and its alias 'value' are present with values of [XXX] and [XXX], but only one is permitted
③ binding:
允許直接在@ModelAttribute注釋的方法參數或@ModelAttribute注釋的方法返回值上聲明禁用數據綁定,這兩種方法都將阻止數據綁定。
默認情況下,binding被設置為true,此時將正常進行數據綁定。將binding設置為false,將禁用數據綁定。
注解應用
1) @ModelAttribute注釋方法
@ModelAttribute注釋方法將在Controller中@RequestMapping注釋方法前被調用。對于@ModelAttribute注釋方法有以下幾種情況:
① @ModelAttribute注釋void返回類型方法
此種情況下,由于方法返回值為void類型,并不會做其他處理。因此若需要向ModeMap中添加屬性,需要通過方法參數ModelMap來完成。
@ModelAttribute
public void modelAttributeWithVoidMethod(ModelMap modelMap) {
modelMap.addAttribute("modelAttributeWithVoidMethod",
"@ModelAttribute注釋在void返回類型的方法上.");
}
② @ModelAttribute注釋非void返回類型方法
此種情況下,①中所使用操作ModelMap方式仍然有效,需要通過方法參數ModelMap來添加屬性。
同時,以返回值類型推斷出的鍵、返回值作為鍵值對添加到ModelMap中。
@ModelAttribute
public String modelAttributeWithStringMethod() {
return "@ModelAttribute注釋String返回類型方法,會自動將返回值添加到ModelMap中,鍵根據返回類型生成.";
}
③ @ModelAttribute注釋非void返回類型方法,并指定其name或value屬性
?此種情況下,①中所使用操作ModelMap方式仍然有效,需要通過方法參數ModelMap來添加屬性。
同時,以@ModelAttribute注解name或value屬性值、返回值作為鍵值對添加到ModelMap中。
@ModelAttribute("defModelAttributeName")
public String modelAttributeWithStringMethodDefName(ModelMap modelMap) {
return "@ModelAttribute注釋String類型返回值方法,會自動將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.";
}
④ @ModelAttribute與@RequestMapping注釋同一方法
此種情況下,@ModelAttribute與@RequestMapping相互作用,會使@RequestMapping表現出稍許差異。@ModelAttribute會使得@RequestMapping注釋方法的某些類型返回值不會使用對應HandlerMethodReturnValueHandler,而是由ModelAttributeMethodProcessor解析。
ModelAttributeMethodProcessor會針對返回值與②或③中進行同樣處理。視圖名稱由RequestToViewNameTranslator根據請求/ModelAttributeWithRequestMapping.do轉換為邏輯視圖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共同作用在一個方法.");
return "webannotations/ModelAttribute";
}
2) @ModelAttribute注釋參數
① @ModelAttribute注釋方法參數
此種情況下,@ModelAttribute注解用于ModelMap數據映射到控制器處理方法的參數中。
@RequestMapping(
value = "/ModelAttributeParameters.do",
method = RequestMethod.GET)
public ModelAndView modelAttributeParameters(@ModelAttribute("defModelAttributeName") String modelAttr,
ModelMap modelMap) throws Exception {
logger.info("@ModelAttribute注釋方法參數,從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中添加數據.
*/
@ModelAttribute
public void modelAttributeWithVoidMethod(ModelMap modelMap) {
modelMap.addAttribute("modelAttributeWithVoidMethod",
"@ModelAttribute注釋在void返回類型的方法上.");
}
/**
* @ModelAttribute注釋
* String返回類型方法.
* 會自動將返回值添加到ModelMap中,鍵根據返回類型生成.
*/
@ModelAttribute
public String modelAttributeWithStringMethod() {
return "@ModelAttribute注釋String返回類型方法,會自動將返回值添加到ModelMap中,鍵根據返回類型生成.";
}
/**
* @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共同作用在一個方法.");
return "webannotations/ModelAttribute";
}
/**
* ModelAttributeParameters.do.
* @ModelAttribute注釋參數,可以從ModelMap中取指定參數值.
*/
@RequestMapping(
value = "/ModelAttributeParameters.do",
method = RequestMethod.GET)
public ModelAndView modelAttributeParameters(@ModelAttribute("defModelAttributeName") String modelAttr,
ModelMap modelMap) throws Exception {
logger.info("@ModelAttribute注釋方法參數,從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實際調用處理程序之后調用,但在DispatcherServlet呈現視圖之前調用.
*/
@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) 啟動服務,訪問//localhost:9199/spring-annotations/WebAnnotations/xxxxx.do,用來查看@ModelAttribute各種使用方法。
① 訪問//localhost:9199/spring-annotations/WebAnnotations/ModelAttribute.do,演示@ModelAttribute注釋單獨方法。
控制臺輸出:
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中,鍵根據返回類型生成.",
"modelAttributeWithVoidMethod":"@ModelAttribute注釋在void返回類型的方法上."
}
可以看到,@ModelAttribute注釋的modelAttributeWithVoidMethod(...)、modelAttributeWithStringMethod()、modelAttributeWithStringMethodDefName(),按照解析的語義已經執(zhí)行。
② 訪問//localhost:9199/spring-annotations/WebAnnotations/ModelAttributeWithRequestMapping.do,演示@ModelAttribute與@RequestMapping共同注釋一個方法。
控制臺輸出:
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"
}
瀏覽器響應:

除了①中所示語義外,還改變了@RequestMapping注釋方法返回值的語義,將返回值按照規(guī)則添加到ModelMap中,視圖則是由/ModelAttributeWithRequestMapping.do來確定的。
③ 訪問//localhost:9199/spring-annotations/WebAnnotations/ModelAttributeParameters.do,演示@ModelAttribute注釋方法參數。
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中,鍵根據返回類型生成."
}
2020-12-16 16:31:41 INFO [c.a.s.w.ModelAttributeController] @ModelAttribute注釋方法參數,從ModelMap中取值:[key=defModelAttributeName, value=@ModelAttribute注釋String類型返回值方法,會自動將返回值添加到ModelMap中,鍵是@ModelAttribute的name或value屬性值.].
可以看到,@ModelAttribute注釋方法將從ModelMap中獲取值,綁定到方法參數上。
總結
@ModelAttribute主要針對ModelMap進行操作,對于傳統(tǒng)的、前后端未分離的應用來說,用處還是很大的。
源碼解析基于spring-framework-5.0.5.RELEASE版本源碼。
若文中存在錯誤和不足,歡迎指正!
到此這篇關于Spring中的@ModelAttribute模型屬性綁定詳解的文章就介紹到這了,更多相關@ModelAttribute模型屬性綁定內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring中的@ExceptionHandler異常攔截器
這篇文章主要介紹了Spring中的@ExceptionHandler異常攔截器,Spring的@ExceptionHandler可以用來統(tǒng)一處理方法拋出的異常,給方法加上@ExceptionHandler注解,這個方法就會處理類中其他方法拋出的異常,需要的朋友可以參考下2024-01-01
詳解spring cloud hystrix請求緩存(request cache)
這篇文章主要介紹了詳解spring cloud hystrix請求緩存(request cache),小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05
Java中StringBuilder字符串類型的操作方法及API整理
Java中的StringBuffer類繼承于AbstractStringBuilder,用來創(chuàng)建非線程安全的字符串類型對象,下面即是對Java中StringBuilder字符串類型的操作方法及API整理2016-05-05

