javascript
Spring MVC-04循序渐进之基于注解的控制器
- 概述
- Spring MVC注解類型
- Controller注解類型
- RequestMapping注解類型
- value屬性
- 其他屬性
- 編寫請求處理方法
- 應用基于注解的控制器
- 目錄結構
- 配置文件
- Controller類
- View
- 測試應用
- 使用@Autowired和@Service進行依賴注入
- 重定向和Flash屬性
- 請求參數和路徑變量
- 獲取請求參數
- 獲取路徑變量
- 使用路徑變量有可能出現的問題
- @ModelAttribute
- @ModelAttribute的第一個用途
- @ModelAttribute的第二個用途
- 總結
概述
Spring MVC-03循序漸進之Spring MVC中我們介紹了傳統的開發方式,其弊端Controller接口實現類只能處理一個單一動作,本篇博文我們來介紹下基于注解的控制器。
Spring MVC注解類型
基于注解的控制器優點如下:
一個控制器可以處理多個請求動作,而一個實現了Controller接口的控制器只能處理一個動作
基于注解的控制器的請求映射不需要存儲在配置文件中,使用RequestMapping注解類型,可以對一個方法進行請求處理。
Controller和RequestMapping注解類型是SpringMVC API最重要的兩個注釋類型,當然了我們這里也會介紹其他一些注解類型
Controller注解類型
org.springframework.stereotype.Controller注解類型用于指示Spring類的實例是一個控制器。
下面是一個帶有@Controller注解的例子
import org.springframework.stereotype.Controller;@Controller public class ArtisanController {}Spring使用注解掃描的方式來找到應用中所有基于注解的控制器類,為了確保Spring能掃描到你的控制器,需要完成兩件事情
確保所有控制器類都在基本包下,并且不要指定一個太寬泛的基本包,這樣會使Spring掃描了無關的包。
RequestMapping注解類型
現在我們需要在控制器類內部為每一個動作開發相應的處理方法,要讓Spring知道哪一種方法來處理它的動作,需要使用org.springframework.web.bind.annotation.RequestMapping注解類型映射的URL與方法。
RequestMapping注釋類型的作用:映射一個請求和一種方法,可以使用@RequestMapping注釋一種方法或者一個類
一個采用了@RequestMapping注解的方法將成為一個請求處理方法,并由調度程序在接收到對應的URL請求時調用
下面是一個@RequestMapping注解方法的控制器類
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping;@Controller public class ArtisanController {@RequestMapping(value="/doSomething")public String doSomething() {// do some bussiness logic herereturn "custoomer";} }使用RequestMapping注解的value屬性將URI映射到方法。在上面的例子中,我們將doSomething映射到doSomething方法,這樣,就可以使用如下URL訪問doSomething方法
http://domain/context/doSomethingvalue屬性
由于value屬性是RequestMapping注解的默認屬性,如果只有唯一的屬性,則可以省略屬性名稱。換句話說
@RequestMapping(value="/doSomething")@RequestMapping("/doSomething")效果是等同的,但是如果超過一個屬性時,就必須要輸入value屬性名稱。
請求映射的值可以是一個空字符,此時該方法被映射到如下網址 http://domain/context
其他屬性
RequestMapping除了具有value屬性,還有其他屬性。比如method屬性用來指示改方法僅處理哪些HTTP方法. 當method為多個值時,后面寫為數組{method1, method2}
例如只有在HTTP POST或者PUT方法時才能訪問到下面的方法
@Controller public class ArtisanController {@RequestMapping(value="/doSomething",method={RequestMethod.POST,RequestMethod.PUT})public String doSomething() {// do some bussiness logic herereturn "customer";} }如果method屬性僅有一個HTTP方法值,則不需要花括號
@RequestMapping(value="/doSomething",method=RequestMethod.POST)如果沒有指定method屬性值,則請求處理方法可以處理任意HTTP方法。
此外RequestMapping注釋類型也可以用來注釋一個控制器類
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod;@Controller @RequestMapping("/artisan") public class ArtisanController {}這種情況下,所有的方法都將映射為相對于類級別的請求,比如下面的deleteArtisan方法
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod;@Controller @RequestMapping("/artisan") public class ArtisanController {@RequestMapping(value="/delete",method={RequestMethod.POST,RequestMethod.PUT})public String deleteArtisan() {// do delete opertaionreturn "artisanList";} }由于控制器類的映射使用了“/artisan” ,而deleteArtisan方法映射為/delete,則如下的URL將映射到該方法上
htpp://domain/context/artisan/delete編寫請求處理方法
每個請求處理方法可以有多個不同類型的參數,以及一個多鐘類型的返回結果。
比如在請求處理方法中需要訪問HttpSession對象,則可以添加HttpSession作為參數,Spring會將對象正確傳遞給方法
@RequestMapping("/uri")public String method(HttpSession session){// do somethingsession.setAttribute(key, value);return ...;}或者,如果需要訪問客戶端環境和HttpServletRequest,則可以在方法簽名上包括這樣的參數
@RequestMapping("/uri")public String method(HttpServletRequest request,Locale locale){// access HttpServletRequest or Locale here return ...;}每個請求處理方法可以有多個不同類型的參數,下面時可以在請求處理方法中出現的參數類型:
javax.servlet.ServletRequest 或 javax.servlet.HttpServletRequest
javax.servlet.ServletResponse
或 javax.servlet.httpHttpServletResponsejavax.servlet.http.HttpSession
org.springframework.web.context.request.WebRequest
或 org.springframework.web.context.request.nativeWebRequestjava.util.Locale
java.io.InputStream 或 java.io.Reader
java.io.OutputStream 或 java.io.Writer
java.security.Principal
HttpEntity<?>
java.util.Map 或 org.springframework.ui.Model
org.springframework.ui.ModelMap
org.springframework.web.servlet.mvc.support.RedirectAttributes
org.springframework.validation.Errors
org.springframework.validation.BindingResult
命令或表單對象
org.springframework.web.util.UriCompontsBuilder
org.springframework.web.util.UriComponentsBuilder
帶@PathVariable, @MatrixVariable注釋的對象
@RequestParam, @RequestHeader, @RequestBody 或 @RequestPart
特別重要的是org.springframework.ui.Model類型不是一個Servlet API類型,而是一個包涵Map的Spring MVC類型。每次調用請求處理方法時,Spring MVC都創建Model對象將其Map注入到各種對象。
請求處理方法可以返回如下類型的對象:
ModelAndView
Model
Map包含模型的屬性
View
代表邏輯視圖名的String
void
提供對Servlet的訪問。以相應HTTP頭部和內容HttpEntity或ResponseEntity對象
Callable
DeferredResult
其他任意類型,Spring將其視作輸出給View的對象模型
應用基于注解的控制器
該處的示例是對前面幾篇博文的重寫,區別于前幾篇博文中的示例在于
- 控制器類中增加了@Controller注解
- Spring配置文件增加了部分元素,下面詳解
目錄結構
maven工程結構如上,在這里,只有一個控制器類,而不是之前示例中的兩個。
同時增加了一個名為index.html的靜態文件,以便Spring MVC Servlet的URL模式設置為”/”時,依然可以訪問靜態資源
配置文件
兩個配置文件,第一個為部署描述符(web.xml文件)中注冊Spring MVC的DispatcherServlet ,第二個Spring MVC的配置文件 springmvc-config.xml
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"><servlet><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/config/springmvc-config.xml</param-value></init-param><load-on-startup>1</load-on-startup> </servlet><servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern></servlet-mapping> </web-app>在部署描述符中servlet-mapping元素中url-pattern設置為 / ,而不是之前實例中的action。 實際上映射動作不必一定是要用某種URL擴展。
當然,當URL設置為/,意味著所有的請求( 包括那些靜態資源)都被映射到DispatcherServlet, 為了正確的處理靜態資源,就必須要在Spring MVC的配置文件中添加一些 resouce元素。
springmvc-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.artisan.springmvc.controller"/><mvc:annotation-driven/><mvc:resources mapping="/css/**" location="/css/"/><mvc:resources mapping="/*.html" location="/"/><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean> </beans>Spring MVC配置文件中最重要的是context:component-scan元素,這是要告訴SpringMVC掃描目標包中的類。
接下來是一個mvc:annotation-driven和兩個mvc:resources。
mvc:annotation-driven元素做的事情內包括注冊用于支持基于注解的控制器的請求處理方法的bean對象
mvc:resources元素用于指示Spring MVC 哪些靜態資源需要單獨處理,即不通過Dispatcher Servlet
在這個示例中,第一個resources元素確保/css目錄下的所有文件可見
第二個允許顯示所有的.html文件
注意:如果沒有annotation-driven,resources元素會阻止任意控制器被調用,如果不需要使用resources,則不需要annotation-driven元素
Controller類
使用Controller注釋類型的一個優點在于:一個控制器類可以包含多個請求處理方法
package com.artisan.springmvc.controller;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping;import com.artisan.springmvc.domain.Product; import com.artisan.springmvc.form.ProductForm;@Controller public class ProductController {private static final Log logger = LogFactory.getLog(ProductController.class);@RequestMapping(value="/product_input")public String inputProduct() {logger.info("inputProduct called");return "ProductForm";}@RequestMapping(value="/product_save")public String saveProduct(ProductForm productForm, Model model) {logger.info("saveProduct called");// no need to create and instantiate a ProductForm// create ProductProduct product = new Product();product.setName(productForm.getName());product.setDescription(productForm.getDescription());try {product.setPrice(Float.parseFloat(productForm.getPrice()));} catch (NumberFormatException e) {}// add productmodel.addAttribute("product", product);return "ProductDetails";} }其中,ProductController#saveProduct()方法的第二個入參
public String saveProduct(ProductForm productForm, Model model)無論是否會使用,SpringMVC都會在每一個請求處理方法被調用時創建一個Model實例,用于增加需要顯示在視圖中的屬性,例如通過調用model.addAttribute("product", product);來添加Product實例。這樣Product實例就可以被添加到HttpServletRequestt中那樣訪問了。
View
ProductForm.jsp
<!DOCTYPE HTML> <html> <head> <title>Add Product Form</title> <style type="text/css">@import url(css/main.css);</style> </head> <body><div id="global"> <form action="product_save" method="post"><fieldset><legend>Add a product</legend><p><label for="name">Product Name: </label><input type="text" id="name" name="name" tabindex="1"></p><p><label for="description">Description: </label><input type="text" id="description" name="description" tabindex="2"></p><p><label for="price">Price: </label><input type="text" id="price" name="price" tabindex="3"></p><p id="buttons"><input id="reset" type="reset" tabindex="4"><input id="submit" type="submit" tabindex="5" value="Add Product"></p></fieldset> </form> </div> </body> </html>ProductDetails.jsp
<!DOCTYPE HTML> <html> <head> <title>Save Product</title> <style type="text/css">@import url(css/main.css);</style> </head> <body> <div id="global"><h4>The product has been saved.</h4><p><h5>Details:</h5>Product Name: ${product.name}<br/>Description: ${product.description}<br/>Price: $${product.price}</p> </div> </body> </html>測試應用
http://localhost:8080/chapter04a/product_input
輸入對應的表格
提交后
http://localhost:8080/chapter04a/product_save
調用saveProduct方法
使用@Autowired和@Service進行依賴注入
使用Spring框架的一個好處是容易進行依賴注入,將依賴注入到Spring MVC控制器的最簡單的方法是通過注解@Autowired到字段或者方法。Autowired注解類型屬于org.springframework.beans.factory.annotation包
分兩步
在配置文件中添加context:component-scan元素掃描依賴基本包
標注注解,如果是服務層,標注@Service
我們新建個maven工程來演示該功能
首先我們先看下Controller類
package com.artisan.springmvc.controller;import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.mvc.support.RedirectAttributes;import com.artisan.springmvc.domain.Product; import com.artisan.springmvc.form.ProductForm; import com.artisan.springmvc.service.ProductService;@Controller public class ProductController {private static final Logger logger = Logger.getLogger(ProductController.class);@Autowiredprivate ProductService productService;@RequestMapping(value = "/product_input")public String inputProduct() {logger.info("inputProduct called ....");return "ProductForm";}@RequestMapping(value = "/product_save", method = RequestMethod.POST)public String saveProduct(ProductForm productForm, RedirectAttributes attributes) {logger.info("saveProduct called ....");// no need to create and instantiate a ProductForm// create ProductProduct product = new Product();product.setName(productForm.getName());product.setDescription(productForm.getDescription());try {product.setPrice(Float.parseFloat(productForm.getPrice()));} catch (NumberFormatException e) {}// add productProduct savedProduct = productService.add(product);attributes.addFlashAttribute("message", "The product has been saved successfully");return "redirect:/product_view/" + savedProduct.getId();}/*** * @param id* @param model* @return* @PathVariable用來獲得請求url中的動態參數*/@RequestMapping(value = "/product_view/{id}")public String getProductById(@PathVariable Long id, Model model) {logger.info("getProductById called ....");Product product = productService.get(id);model.addAttribute("product", product);return "ProductView";}}該ProductController類與上個例子中的ProductController類相比,做了一些調整
1. 首先自動注入了ProductService ,加了@AutoWired注解
private ProductService productService;public ProductService getProductService() {return productService;}@Autowiredpublic void setProductService(ProductService productService) {this.productService = productService;}或者
@Autowired private ProductService productService;productService是一個提供跟蹤處理產品方法的接口,為productService字段或者set方法注入@Autowired會使ProductService的一個實例被注入到ProductController實例中。
為了使類能夠被Spring掃描到,必須要標注@Service
ProductService接口
package com.artisan.springmvc.service;import com.artisan.springmvc.domain.Product;public interface ProductService {Product add(Product product);Product get(long id); }ProductServiceImpl類
package com.artisan.springmvc.service;import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong;import org.springframework.stereotype.Service;import com.artisan.springmvc.domain.Product; /*** * @author Mr.Yang* 標注了@Service的服務層**/ @Service public class ProductServiceImpl implements ProductService {private Map<Long, Product> products = new HashMap<Long, Product>();// 使用AtomicLong能讓long的操作在多線程下保持原子型private AtomicLong generator = new AtomicLong();public ProductServiceImpl() {Product product = new Product();add(product);}@Overridepublic Product add(Product product) {long newId = generator.incrementAndGet();product.setId(newId);products.put(newId, product);return product;}@Overridepublic Product get(long id) {return products.get(id);} }2. 然后在SpringMVC配置文件中有兩個component-scan元素,一個是用于掃描控制器類,另一個新增加的為掃描服務類
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:p="http://www.springframework.org/schema/p"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.artisan.springmvc.controller"/><context:component-scan base-package="com.artisan.springmvc.service"/><mvc:annotation-driven/><mvc:resources mapping="/css/**" location="/css/"/><mvc:resources mapping="/*.html" location="/"/><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/></bean> </beans>重定向和Flash屬性
經常寫Servlet/JSP的童鞋都知道轉發和重定向的區別
轉發比重定向要快,因為轉發不經過客戶端,而重定向會經過客戶端。但是有時候采用重定向會更好,比如需要重定向到一個外部網站,則無法使用轉發
另外一個使用重定向的場景是避免在用戶重新加載頁面的時候再次調用相同的動作 ,比如,這個示例中, 當提交產品表單時,saveProduct方法會被調用,并執行相應的動作。在真實應用中,這些所述產品會加入到數據庫中。但是如果提交表單后重新加載頁面,saveProduct會被再此調用,同樣的產品可能被再此添加。為了避免這種情況,提交表單后,你可能更愿意將用戶重定向到一個不同的頁面。這個網頁任意加載都沒有副作用。我們這個示例中,提交表單后,將用戶重定向到一個ViewProduct頁面.
在這個示例中,ProductController#saveProduct方法 返回
return "redirect:/product_view/" + savedProduct.getId();這里使用重定向,而不是轉發來防止當用戶重新加載頁面時,saveProduct被二次調用。
使用重定向有個不方便的地方:無法輕松的傳值給目標頁面,而轉發則可以簡單的將屬性添加到Model中,使目標頁面輕松訪問。由于重定向經過客戶端,所以Model中的一切都在重定向時丟失了。 幸運的是Spring3.1版本及更高的版本通過Flash屬性提供了一種重定向傳值的方法
要使用Flash屬性,必須在Spring MVC的配置文件中有一個<mvc:annotation-driven/>元素,然后,還必須在方法上添加一個新的參數類型 org.springframework.web.servlet.mvc.support.RedirectAttributes
如下所示
請求參數和路徑變量
獲取請求參數
請求參數和路徑變量都可以用于發送值給服務器,二者都是URL的一部分。 請求參數采用key=value形式,并用&分割。
比如
http://localhost:8080/chapter04b/productRetrive?productId=5在傳統的Servlet編程中,可以使用HttpServletRequest的getParameter方法來獲取一個請求參數值
String productId=httpServletRequest.getParameter("productId");Spring MVC則提供了一個更簡單的方法來獲取請求參數的值:org.springframework.web.bind.annotation.RequestParam注釋類型來獲取注釋方法參數,比如
public void sendProduct(@RequestParam int productId)正如所示,@RequestParam注解的參數類型不一定是字符串。
獲取路徑變量
路徑變量類似請求參數,但是沒有key部分,只有一個值, 比如我們這個示例中 product_view動作映射到如下URL
/product_view/productId其中productId表示產品標識符的整數。在SpringMVC中,productId被稱作路徑變量,用來發送一個值到服務器
接下來我們看下viewProduct方法演示了一個路徑變量的使用
/*** * @param id* @param model* @return* @PathVariable用來獲得請求url中的動態參數*/@RequestMapping(value = "/product_view/{id}")public String viewProduct(@PathVariable Long id, Model model) {logger.info("getProductById called ....");Product product = productService.get(id);model.addAttribute("product", product);return "ProductView";}為了使用路徑變量,首先需要在RequestMapping注解的值屬性中添加一個變量,該變量必須放在花括號之間,例如下面的RequestMapping注解定義一個名為id的路徑變量
@RequestMapping(value = "/product_view/{id}")然后在方法簽名中添加一個同名變量,并添加上@PathVariable注解。 當viewProduct方法別調用時,請求URL的id值將被復制到路徑變量中,并可以在方法中使用。 路徑變量的類型可以不是字符串,Spring MVC將盡量轉換為非字符串類型,這個強大的功能,后續在數據綁定和表單參數中詳解。
可以在請求映射中使用多個路徑變量,比如userId和orderId兩個路徑變量
@RequestMapping(value="/produtc_view/{userId}/{orderId}")直接在瀏覽器中輸入URL,來測試viewProduct方法的路徑變量
http://localhost:8080/chapter04b/product_view/5使用路徑變量有可能出現的問題
有時候,使用路徑變量會遇到一個小問題:在某些情況下,瀏覽器可能會誤解路徑變量。 考慮下面的URL
http://example.com/context/abc瀏覽器會(正確)認為abc是一個動作。 任何靜態文件路徑的解析,比如css文件,將使用http://example.com/context作為基本路徑。
這就是說,若服務器發送的網頁包含如下img元素 <img src='logo.png'/>,改瀏覽器將試圖通過http://example.com/context/logo.png來加載logo.png
然而,若一個應用程序被部署為默認上線文(默認上下文是一個空字符串),則對于同一個目標的URL,會是這樣
http://example.com/abc下面是帶有路徑變量的URL
http://example.com/abc/1這種情況下,瀏覽器會認為abc是上下文,沒有動作。 如果在頁面中使用<img src='logo.png'/>,瀏覽器將試圖通過http://example.com/abc/logo.png來尋找圖片,并且它將找不到圖片。
幸運的是,我們有個簡單的解決方法,即通過JSTL標記的URL。 標簽會通過正確解析URL來修復該問題。
比如我們該案例中的css加載
<style type="text/css">@import url(css/main.css);</style>改為
<style type="text/css">@import url("<c:url value="/css/main.css"/>");</style>若程序部署為默認的上下文,鏈接標簽會將改URL轉換成如下形式
<style type="text/css">@import url(css/main.css);</style>若程序不在默認上下文中,則會被轉換為
<style type="text/css">@import url("<c:url value="/chapter04b/css/main.css"/>");</style>我們這個示例中的上下文為chapter04b , 通過f12查看如下方式加載css
http://localhost:8080/chapter04b/css/main.css
如果寫成@import url(css/main.css);將加載不到css的樣式。
@ModelAttribute
前面講到Spring MVC在每次調用請求處理方法時,都會創建Model類型的一個實例。若打算使用該實例,則可以在方法中添加一個Model類型的參數。事實上還可以使用在方法中添加ModelAttribute注釋類型來訪問Model實例。 該注釋類型也是org.springframework.web.bind.annotation包的成員。
@ModelAttribute的第一個用途
可以用@ModelAttribute來注釋方法參數或者方法。
帶@ModelAttribute注解的方法會將其輸入的或創建的參數對象添加到Model對象中(若方法中沒有顯式添加)。
比如,Spring MVC將在每次調用submitOrder方法時創建一個Order實例
@RequestMapping(value="/submitOrder",method=RequestMethod.Post) public String submitOrder(@ModelAttribute("newOrder") Order order,Model model){... }輸入或者創建的Order實例將用newOrder鍵值添加到Model對象中,如果未定義鍵值名,則使用該對象類型的名稱。
比如,每次調用如下方法,會使用鍵值order將Order實例添加到Model對象中
@RequestMapping(value="/submitOrder",method=RequestMethod.Post) public String submitOrder(@ModelAttribute Order order,Model model){... }@ModelAttribute的第二個用途
@ModelAttribute的第二個用途是標注一個非請求的處理方法。 被@ModelAttribute注釋的方法會在每次調用該控制器類的請求處理方法時被調用。
這就意味著,如果一個控制器類有兩個請求處理方法,以及一個帶有@ModelAttribute注解的方法,該方法的調用次數就會比每個處理請求方法更加頻繁。
Spring MVC會在調用請求處理方法之前調用帶有@ModelAttribute注解的方法,帶@ModelAttribute注解的方法可以返回一個對象或者一個void類型,
如果返回一個對象,則返回對象會自動添加到Model中
@ModelAttribute public Product addProduct(@RequestParam String productId){return productService.get(produtId) }若返回的是void,這還必須添加一個Model類型的參數,并自行將實例添加到Model中
@ModelAttribute public void populateModel(@RequestParam String id,Model model){model.addAttribute(new Account(id)); }總結
這里介紹了如何編寫基于注解的控制器的Spring MVC應用,也講解了各種注解類、方法或者方法的參數的注釋類型
總結
以上是生活随笔為你收集整理的Spring MVC-04循序渐进之基于注解的控制器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring MVC-03循序渐进之Sp
- 下一篇: Spring MVC-06循序渐进之Co