天天看點

@autowired注解作用_Java筆記:SpringMVC常用注解詳解

連結:https://segmentfault.com/a/1190000014466021

作者:JeffreyLcm

@autowired注解作用_Java筆記:SpringMVC常用注解詳解

1、@Controller

在SpringMVC 中,控制器Controller 負責處理由DispatcherServlet 分發的請求,它把使用者請求的資料經過業務處理層處理之後封裝成一個Model ,然後再把該Model 傳回給對應的View 進行展示。在SpringMVC 中提供了一個非常簡便的定義Controller 的方法,你無需繼承特定的類或實作特定的接口,隻需使用@Controller 标記一個類是Controller ,然後使用@RequestMapping 和@RequestParam 等一些注解用以定義URL 請求和Controller 方法之間的映射,這樣的Controller 就能被外界通路到。此外Controller 不會直接依賴于HttpServletRequest 和HttpServletResponse 等HttpServlet 對象,它們可以通過Controller 的方法參數靈活的擷取到。

@Controller 用于标記在一個類上,使用它标記的類就是一個SpringMVC Controller 對象。分發處理器将會掃描使用了該注解的類的方法,并檢測該方法是否使用了@RequestMapping 注解。@Controller 隻是定義了一個控制器類,而使用@RequestMapping 注解的方法才是真正處理請求的處理器。單單使用@Controller 标記在一個類上還不能真正意義上的說它就是SpringMVC 的一個控制器類,因為這個時候Spring 還不認識它。那麼要如何做Spring 才能認識它呢?這個時候就需要我們把這個控制器類交給Spring 來管理。有兩種方式:

  (1)在SpringMVC 的配置檔案中定義MyController 的bean 對象。

  (2)在SpringMVC 的配置檔案中告訴Spring 該到哪裡去找标記為@Controller 的Controller 控制器。

< context:component-scan base-package = "com.host.app.web" />//路徑寫到controller的上一層(掃描包詳解見下面淺析)
           

2、@RequestMapping

RequestMapping是一個用來處理請求位址映射的注解,可用于類或方法上。用于類上,表示類中的所有響應請求的方法都是以該位址作為父路徑。

RequestMapping注解有六個屬性,下面我們把她分成三類進行說明(下面有相應示例)。

1、 value, method;

value: 指定請求的實際位址,指定的位址可以是URI Template 模式(後面将會說明);

method: 指定請求的method類型, GET、POST、PUT、DELETE等;

2、consumes,produces

consumes: 指定處理請求的送出内容類型(Content-Type),例如application/json, text/html;

produces: 指定傳回的内容類型,僅當request請求頭中的(Accept)類型中包含該指定類型才傳回;

3、params,headers

params: 指定request中必須包含某些參數值是,才讓該方法處理。

headers: 指定request中必須包含某些指定的header值,才能讓該方法處理請求。

3、@Resource和@Autowired

@Resource和@Autowired都是做bean的注入時使用,其實@Resource并不是Spring的注解,它的包是javax.annotation.Resource,需要導入,但是Spring支援該注解的注入。

1、共同點

兩者都可以寫在字段和setter方法上。兩者如果都寫在字段上,那麼就不需要再寫setter方法。

2、不同點

(1)@Autowired

@Autowired為Spring提供的注解,需要導入包org.springframework.beans.factory.annotation.Autowired;隻按照byType注入。

public class TestServiceImpl {    // 下面兩種@Autowired隻要使用一種即可    @Autowired    private UserDao userDao; // 用于字段上        @Autowired    public void setUserDao(UserDao userDao) { // 用于屬性的方法上        this.userDao = userDao;    }}
           

@Autowired注解是按照類型(byType)裝配依賴對象,預設情況下它要求依賴對象必須存在,如果允許null值,可以設定它的required屬性為false。如果我們想使用按照名稱(byName)來裝配,可以結合@Qualifier注解一起使用。如下:

public class TestServiceImpl {

@[email protected]("userDao")private UserDao userDao; 
           

}(2)@Resource

@Resource預設按照ByName自動注入,由J2EE提供,需要導入包javax.annotation.Resource。@Resource有兩個重要的屬性:name和type,而Spring将@Resource注解的name屬性解析為bean的名字,而type屬性則解析為bean的類型。是以,如果使用name屬性,則使用byName的自動注入政策,而使用type屬性時則使用byType自動注入政策。如果既不制定name也不制定type屬性,這時将通過反射機制使用byName自動注入政策。

public class TestServiceImpl {    // 下面兩種@Resource隻要使用一種即可    @Resource(name="userDao")    private UserDao userDao; // 用于字段上        @Resource(name="userDao")    public void setUserDao(UserDao userDao) { // 用于屬性的setter方法上        this.userDao = userDao;    }}
           

注:最好是将@Resource放在setter方法上,因為這樣更符合面向對象的思想,通過set、get去操作屬性,而不是直接去操作屬性。

@Resource裝配順序:

①如果同時指定了name和type,則從Spring上下文中找到唯一比對的bean進行裝配,找不到則抛出異常。

②如果指定了name,則從上下文中查找名稱(id)比對的bean進行裝配,找不到則抛出異常。

③如果指定了type,則從上下文中找到類似比對的唯一bean進行裝配,找不到或是找到多個,都會抛出異常。

④如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有比對,則回退為一個原始類型進行比對,如果比對則自動裝配。

@Resource的作用相當于@Autowired,隻不過@Autowired按照byType自動注入。

4、@ModelAttribute和 @SessionAttributes

代表的是:該Controller的所有方法在調用前,先執行此@ModelAttribute方法,可用于注解和方法參數中,可以把這個@ModelAttribute特性,應用在BaseController當中,所有的Controller繼承BaseController,即可實作在調用Controller時,先執行@ModelAttribute方法。

@SessionAttributes即将值放到session作用域中,寫在class上面。

具體示例參見下面:使用 @ModelAttribute 和 @SessionAttributes 傳遞和儲存資料

5、@PathVariable

用于将請求URL中的模闆變量映射到功能處理方法的參數上,即取出uri模闆中的變量作為參數。如:

@Controller  public class TestController {       @RequestMapping(value="/user/{userId}/roles/{roleId}",method = RequestMethod.GET)       public String getLogin(@PathVariable("userId") String userId,           @PathVariable("roleId") String roleId){           System.out.println("User Id : " + userId);           System.out.println("Role Id : " + roleId);           return "hello";       }       @RequestMapping(value="/product/{productId}",method = RequestMethod.GET)       public String getProduct(@PathVariable("productId") String productId){             System.out.println("Product Id : " + productId);             return "hello";       }       @RequestMapping(value="/javabeat/{regexp1:[a-z-]+}",             method = RequestMethod.GET)       public String getRegExp(@PathVariable("regexp1") String regexp1){             System.out.println("URI Part 1 : " + regexp1);             return "hello";       }  }
           

6、@requestParam

@requestParam主要用于在SpringMVC背景控制層擷取參數,類似一種是request.getParameter("name"),它有三個常用參數:defaultValue = "0", required = false, value = "isApp";defaultValue 表示設定預設值,required 銅過boolean設定是否是必須要傳入的參數,value 值表示接受的傳入的參數類型。

7、@ResponseBody

作用: 該注解用于将Controller的方法傳回的對象,通過适當的HttpMessageConverter轉換為指定格式後,寫入到Response對象的body資料區。

使用時機:傳回的資料不是html标簽的頁面,而是其他某種格式的資料時(如json、xml等)使用;

8、@Component

相當于通用的注解,當不知道一些類歸到哪個層時使用,但是不建議。

9、@Repository

用于注解dao層,在daoImpl類上面注解。

注:1、使用 @RequestMapping 來映射 Request 請求與處理器

方式一、通過常見的類路徑和方法路徑結合通路controller方法

方式二、使用uri模闆

@[email protected] ( "/test/{variable1}" )public class MyController {    @RequestMapping ( "/showView/{variable2}" )    public ModelAndView showView( @PathVariable String variable1, @PathVariable ( "variable2" ) int variable2) {       ModelAndView modelAndView = new ModelAndView();       modelAndView.setViewName( "viewName" );       modelAndView.addObject( " 需要放到 model 中的屬性名稱 " , " 對應的屬性值,它是一個對象 " );       return modelAndView;    }} 
           

URI 模闆就是在URI 中給定一個變量,然後在映射的時候動态的給該變量指派。如URI 模闆http://localhost/app/{variable1}/index.html ,這個模闆裡面包含一個變量variable1 ,那麼當我們請求http://localhost/app/hello/in... 的時候,該URL 就跟模闆相比對,隻是把模闆中的variable1 用hello 來取代。這個變量在SpringMVC 中是使用@PathVariable 來标記的。在SpringMVC 中,我們可以使用@PathVariable 來标記一個Controller 的處理方法參數,表示該參數的值将使用URI 模闆中對應的變量的值來指派。

代碼中我們定義了兩個URI 變量,一個是控制器類上的variable1 ,一個是showView 方法上的variable2 ,然後在showView 方法的參數裡面使用@PathVariable 标記使用了這兩個變量。是以當我們使用/test/hello/showView/2.do 來請求的時候就可以通路到MyController 的showView 方法,這個時候variable1 就被賦予值hello ,variable2 就被賦予值2 ,然後我們在showView 方法參數裡面标注了參數variable1 和variable2 是來自通路路徑的path 變量,這樣方法參數variable1 和variable2 就被分别賦予hello 和2 。方法參數variable1 是定義為String 類型,variable2 是定義為int 類型,像這種簡單類型在進行指派的時候Spring 是會幫我們自動轉換的。

在上面的代碼中我們可以看到在标記variable1 為path 變量的時候我們使用的是@PathVariable ,而在标記variable2 的時候使用的是@PathVariable(“variable2”) 。這兩者有什麼差別呢?第一種情況就預設去URI 模闆中找跟參數名相同的變量,但是這種情況隻有在使用debug 模式進行編譯的時候才可以,而第二種情況是明确規定使用的就是URI 模闆中的variable2 變量。當不是使用debug 模式進行編譯,或者是所需要使用的變量名跟參數名不相同的時候,就要使用第二種方式明确指出使用的是URI 模闆中的哪個變量。

除了在請求路徑中使用URI 模闆,定義變量之外,@RequestMapping 中還支援通配符“* ”。如下面的代碼我就可以使用/myTest/whatever/wildcard.do 通路到Controller 的testWildcard 方法。如:

@[email protected] ( "/myTest" )public class MyController {    @RequestMapping ( "*/wildcard" )    public String testWildcard() {       System. out .println( "wildcard------------" );       return "wildcard" ;    }  }
           

當@RequestParam中沒有指定參數名稱時,Spring 在代碼是debug 編譯的情況下會預設取更方法參數同名的參數,如果不是debug 編譯的就會報錯。

2、使用 @RequestMapping 的一些進階用法

(1)params屬性

@RequestMapping (value= "testParams" , params={ "param1=value1" , "param2" , "!param3" })    public String testParams() {       System. out .println( "test Params..........." );       return "testParams" ;    }
           

用@RequestMapping 的params 屬性指定了三個參數,這些參數都是針對請求參數而言的,它們分别表示參數param1 的值必須等于value1 ,參數param2 必須存在,值無所謂,參數param3 必須不存在,隻有當請求/testParams.do 并且滿足指定的三個參數條件的時候才能通路到該方法。是以當請求/testParams.do?param1=value1¶m2=value2 的時候能夠正确通路到該testParams 方法,當請求/testParams.do?param1=value1¶m2=value2¶m3=value3 的時候就不能夠正常的通路到該方法,因為在@RequestMapping 的params 參數裡面指定了參數param3 是不能存在的。

(2)method屬性

@RequestMapping (value= "testMethod" , method={RequestMethod. GET , RequestMethod. DELETE })    public String testMethod() {       return "method" ;    }
           

在上面的代碼中就使用method 參數限制了以GET 或DELETE 方法請求/testMethod 的時候才能通路到該Controller 的testMethod 方法。

(3)headers屬性

@RequestMapping (value= "testHeaders" , headers={ "host=localhost" , "Accept" })    public String testHeaders() {       return "headers" ;    }
           

headers 屬性的用法和功能與params 屬性相似。在上面的代碼中當請求/testHeaders.do 的時候隻有當請求頭包含Accept 資訊,且請求的host 為localhost 的時候才能正确的通路到testHeaders 方法。

3、 @RequestMapping 标記的處理器方法支援的方法參數和傳回類型

  1. 支援的方法參數類型(1 )HttpServlet 對象,主要包括HttpServletRequest 、HttpServletResponse 和HttpSession 對象。 這些參數Spring 在調用處理器方法的時候會自動給它們指派,是以當在處理器方法中需要使用到這些對象的時候,可以直接在方法上給定一個方法參數的申明,然後在方法體裡面直接用就可以了。但是有一點需要注意的是在使用HttpSession 對象的時候,如果此時HttpSession 對象還沒有建立起來的話就會有問題。(2 )Spring 自己的WebRequest 對象。 使用該對象可以通路到存放在HttpServletRequest 和HttpSession 中的屬性值。(3 )InputStream 、OutputStream 、Reader 和Writer 。 InputStream 和Reader 是針對HttpServletRequest 而言的,可以從裡面取資料;OutputStream 和Writer 是針對HttpServletResponse 而言的,可以往裡面寫資料。(4 )使用@PathVariable 、@RequestParam 、@CookieValue 和@RequestHeader 标記的參數。(5 )使用@ModelAttribute 标記的參數。(6 )java.util.Map 、Spring 封裝的Model 和ModelMap 。 這些都可以用來封裝模型資料,用來給視圖做展示。(7 )實體類。 可以用來接收上傳的參數。(8 )Spring 封裝的MultipartFile 。 用來接收上傳檔案的。(9 )Spring 封裝的Errors 和BindingResult 對象。 這兩個對象參數必須緊接在需要驗證的實體對象參數之後,它裡面包含了實體對象的驗證結果。
  2. 支援的傳回類型(1 )一個包含模型和視圖的ModelAndView 對象。(2 )一個模型對象,這主要包括Spring 封裝好的Model 和ModelMap ,以及java.util.Map ,當沒有視圖傳回的時候視圖名稱将由RequestToViewNameTranslator 來決定。(3 )一個View 對象。這個時候如果在渲染視圖的過程中模型的話就可以給處理器方法定義一個模型參數,然後在方法體裡面往模型中添加值。(4 )一個String 字元串。這往往代表的是一個視圖名稱。這個時候如果需要在渲染視圖的過程中需要模型的話就可以給處理器方法一個模型參數,然後在方法體裡面往模型中添加值就可以了。(5 )傳回值是void 。這種情況一般是我們直接把傳回結果寫到HttpServletResponse 中了,如果沒有寫的話,那麼Spring 将會利用RequestToViewNameTranslator 來傳回一個對應的視圖名稱。如果視圖中需要模型的話,處理方法與傳回字元串的情況相同。(6 )如果處理器方法被注解@ResponseBody 标記的話,那麼處理器方法的任何傳回類型都會通過HttpMessageConverters 轉換之後寫到HttpServletResponse 中,而不會像上面的那些情況一樣當做視圖或者模型來處理。(7 )除以上幾種情況之外的其他任何傳回類型都會被當做模型中的一個屬性來處理,而傳回的視圖還是由RequestToViewNameTranslator 來決定,添加到模型中的屬性名稱可以在該方法上用@ModelAttribute(“attributeName”) 來定義,否則将使用傳回類型的類名稱的首字母小寫形式來表示。使用@ModelAttribute 标記的方法會在@RequestMapping 标記的方法執行之前執行。

4、使用 @ModelAttribute 和 @SessionAttributes 傳遞和儲存資料

SpringMVC 支援使用 @ModelAttribute 和 @SessionAttributes 在不同的模型(model)和控制器之間共享資料。 @ModelAttribute 主要有兩種使用方式,一種是标注在方法上,一種是标注在 Controller 方法參數上。

當 @ModelAttribute 标記在方法上的時候,該方法将在處理器方法執行之前執行,然後把傳回的對象存放在 session 或模型屬性中,屬性名稱可以使用 @ModelAttribute(“attributeName”) 在标記方法的時候指定,若未指定,則使用傳回類型的類名稱(首字母小寫)作為屬性名稱。關于 @ModelAttribute 标記在方法上時對應的屬性是存放在 session 中還是存放在模型中,我們來做一個實驗,看下面一段代碼。

@[email protected] ( "/myTest" )public class MyController {    @ModelAttribute ( "hello" )    public String getModel() {       System. out .println( "-------------Hello---------" );       return "world" ;    }    @ModelAttribute ( "intValue" )    public int getInteger() {       System. out .println( "-------------intValue---------------" );       return 10;    }    @RequestMapping ( "sayHello" )    public void sayHello( @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpSession session) throws IOException {       writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num);       writer.write( "" );       Enumeration enume = session.getAttributeNames();       while (enume.hasMoreElements())           writer.write(enume.nextElement() + "" );    }    @ModelAttribute ( "user2" )    public User getUser(){       System. out .println( "---------getUser-------------" );       return new User(3, "user2" );    }}
           

當我們請求 /myTest/sayHello.do 的時候使用 @ModelAttribute 标記的方法會先執行,然後把它們傳回的對象存放到模型中。最終通路到 sayHello 方法的時候,使用 @ModelAttribute 标記的方法參數都能被正确的注入值。執行結果如下所示:

Hello world,Hello user210

由執行結果我們可以看出來,此時 session 中沒有包含任何屬性,也就是說上面的那些對象都是存放在模型屬性中,而不是存放在 session 屬性中。那要如何才能存放在 session 屬性中呢?這個時候我們先引入一個新的概念 @SessionAttributes ,它的用法會在講完 @ModelAttribute 之後介紹,這裡我們就先拿來用一下。我們在 MyController 類上加上 @SessionAttributes 屬性标記哪些是需要存放到 session 中的。看下面的代碼:@[email protected] ( "/myTest" )@SessionAttributes (value={ "intValue" , "stringValue" }, types={User. class })public class MyController {    @ModelAttribute ( "hello" )    public String getModel() {       System. out .println( "-------------Hello---------" );       return "world" ;    }    @ModelAttribute ( "intValue" )    public int getInteger() {       System. out .println( "-------------intValue---------------" );       return 10;    }       @RequestMapping ( "sayHello" )    public void sayHello(Map map, @ModelAttribute ( "hello" ) String hello, @ModelAttribute ( "intValue" ) int num, @ModelAttribute ( "user2" ) User user, Writer writer, HttpServletRequest request) throws IOException {       map.put( "stringValue" , "String" );       writer.write( "Hello " + hello + " , Hello " + user.getUsername() + num);       writer.write( "" );       HttpSession session = request.getSession();       Enumeration enume = session.getAttributeNames();       while (enume.hasMoreElements())           writer.write(enume.nextElement() + "" );       System. out .println(session);    }    @ModelAttribute ( "user2" )    public User getUser() {       System. out .println( "---------getUser-------------" );       return new User(3, "user2" );    }}
           

在上面代碼中我們指定了屬性為 intValue 或 stringValue 或者類型為 User 的都會放到 Session中,利用上面的代碼當我們通路 /myTest/sayHello.do 的時候,結果如下:

Hello world,Hello user210

仍然沒有列印出任何 session 屬性,這是怎麼回事呢?怎麼定義了把模型中屬性名為 intValue 的對象和類型為 User 的對象存到 session 中,而實際上沒有加進去呢?難道我們錯啦?我們當然沒有錯,隻是在第一次通路 /myTest/sayHello.do 的時候 @SessionAttributes 定義了需要存放到 session 中的屬性,而且這個模型中也有對應的屬性,但是這個時候還沒有加到 session 中,是以 session 中不會有任何屬性,等處理器方法執行完成後 Spring 才會把模型中對應的屬性添加到 session 中。是以當請求第二次的時候就會出現如下結果:

Hello world,Hello user210

user2

intValue

stringValue

當 @ModelAttribute 标記在處理器方法參數上的時候,表示該參數的值将從模型或者 Session 中取對應名稱的屬性值,該名稱可以通過 @ModelAttribute(“attributeName”) 來指定,若未指定,則使用參數類型的類名稱(首字母小寫)作為屬性名稱。

5、@PathVariable和@RequestParam的差別

請求路徑上有個id的變量值,可以通過@PathVariable來擷取 @RequestMapping(value = "/page/{id}", method = RequestMethod.GET) @RequestParam用來獲得靜态的URL請求入參 spring注解時action裡用到。

簡介:

handler method 參數綁定常用的注解,我們根據他們處理的Request的不同内容部分分為四類:(主要講解常用類型)

A、處理requet uri 部分(這裡指uri template中variable,不含queryString部分)的注解: @PathVariable;

B、處理request header部分的注解: @RequestHeader, @CookieValue;

C、處理request body部分的注解:@RequestParam, @RequestBody;

D、處理attribute類型是注解: @SessionAttributes, @ModelAttribute;

(1)、@PathVariable

當使用@RequestMapping URI template 樣式映射時, 即 someUrl/{paramId}, 這時的paramId可通過 @Pathvariable注解綁定它傳過來的值到方法的參數上。

示例代碼:

@Controller  @RequestMapping("/owners/{ownerId}")  public class RelativePathUriTemplateController {      @RequestMapping("/pets/{petId}")    public void findPet(@PathVariable String ownerId, @PathVariable String petId, Model model) {          // implementation omitted     }  } 
           

上面代碼把URI template 中變量 ownerId的值和petId的值,綁定到方法的參數上。若方法參數名稱和需要綁定的uri template中變量名稱不一緻,需要在@PathVariable("name")指定uri template中的名稱。

(2)、 @RequestHeader、@CookieValue

@RequestHeader 注解,可以把Request請求header部分的值綁定到方法的參數上。

示例代碼:

這是一個Request 的header部分:

Host localhost:8080 Accept text/html,application/xhtml+xml,application/xml;q=0.9 Accept-Language fr,en-gb;q=0.7,en;q=0.3 Accept-Encoding gzip,deflate Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive 300

@RequestMapping("/displayHeaderInfo.do")  public void displayHeaderInfo(@RequestHeader("Accept-Encoding") String encoding,                                @RequestHeader("Keep-Alive") long keepAlive)  {  }  
           

上面的代碼,把request header部分的 Accept-Encoding的值,綁定到參數encoding上了, Keep-Alive header的值綁定到參數keepAlive上。

@CookieValue 可以把Request header中關于cookie的值綁定到方法的參數上。

例如有如下Cookie值:

  JSESSIONID=415A4AC178C59DACE0B2C9CA727CDD84

@RequestMapping("/displayHeaderInfo.do")  public void displayHeaderInfo(@CookieValue("JSESSIONID") String cookie)  {  } 
           

即把JSESSIONID的值綁定到參數cookie上。

(3)、@RequestParam, @RequestBody

@RequestParam

A) 常用來處理簡單類型的綁定,通過Request.getParameter() 擷取的String可直接轉換為簡單類型的情況( String--> 簡單類型的轉換操作由ConversionService配置的轉換器來完成);因為使用request.getParameter()方式擷取參數,是以可以處理get 方式中queryString的值,也可以處理post方式中 body data的值;

B)用來處理Content-Type: 為 application/x-www-form-urlencoded編碼的内容,送出方式GET、POST;

C) 該注解有兩個屬性: value、required; value用來指定要傳入值的id名稱,required用來訓示參數是否必須綁定;

示例代碼:

@Controller  @RequestMapping("/pets")  @SessionAttributes("pet")  public class EditPetForm {      @RequestMapping(method = RequestMethod.GET)   public String setupForm(@RequestParam("petId") int petId, ModelMap model) {         Pet pet = this.clinic.loadPet(petId);     model.addAttribute("pet", pet);     return "petForm";     }} 
           

@RequestBody

該注解常用來處理Content-Type: 不是application/x-www-form-urlencoded編碼的内容,例如application/json, application/xml等;

它是通過使用HandlerAdapter 配置的HttpMessageConverters來解析post data body,然後綁定到相應的bean上的。

因為配置有FormHttpMessageConverter,是以也可以用來處理 application/x-www-form-urlencoded的内容,處理完的結果放在一個MultiValueMap裡,這種情況在某些特殊需求下使用,詳情檢視FormHttpMessageConverter api;

示例代碼:

@RequestMapping(value = "/something", method = RequestMethod.PUT)  public void handle(@RequestBody String body, Writer writer) throws IOException {    writer.write(body);  } 
           

(4)、@SessionAttributes, @ModelAttribute

@SessionAttributes:

該注解用來綁定HttpSession中的attribute對象的值,便于在方法中的參數裡使用。

該注解有value、types兩個屬性,可以通過名字和類型指定要使用的attribute 對象;

示例代碼:

@Controller  @RequestMapping("/editPet.do")  @SessionAttributes("pet")  public class EditPetForm {      // ...   } @ModelAttribute
           

該注解有兩個用法,一個是用于方法上,一個是用于參數上;

用于方法上時: 通常用來在處理@RequestMapping之前,為請求綁定需要從背景查詢的model;

用于參數上時: 用來通過名稱對應,把相應名稱的值綁定到注解的參數bean上;要綁定的值來源于:

A) @SessionAttributes 啟用的attribute 對象上;

B) @ModelAttribute 用于方法上時指定的model對象;

C) 上述兩種情況都沒有時,new一個需要綁定的bean對象,然後把request中按名稱對應的方式把值綁定到bean中。

用到方法上@ModelAttribute的示例代碼:

@ModelAttribute  public Account addAccount(@RequestParam String number) {      return accountManager.findAccount(number);  } 
           

這種方式實際的效果就是在調用@RequestMapping的方法之前,為request對象的model裡put(“account”, Account)。

用在參數上的@ModelAttribute示例代碼:

@RequestMapping(value="/owners/{ownerId}/pets/{petId}/edit", method = RequestMethod.POST)  public String processSubmit(@ModelAttribute Pet pet) {       } 
           

首先查詢 @SessionAttributes有無綁定的Pet對象,若沒有則查詢@ModelAttribute方法層面上是否綁定了Pet對象,若沒有則将URI template中的值按對應的名稱綁定到Pet對象的各屬性上。

6、< context:component-scan base-package = "" />淺析component-scan 預設掃描的注解類型是 @Component,不過,在 @Component 語義基礎上細化後的 @Repository, @Service 和 @Controller 也同樣可以獲得 component-scan 的青睐

有了,另一個标簽根本可以移除掉,因為已經被包含進去了

另外還提供了兩個子标簽

  1. //指定掃描的路徑
  2. //排除掃描的路徑

有一個use-default-filters屬性,屬性預設為true,表示會掃描指定包下的全部的标有@Component的類,并注冊成bean.也就是@Component的子注解@Service,@Reposity等。

這種掃描的粒度有點太大,如果你隻想掃描指定包下面的Controller或其他内容則設定use-default-filters屬性為false,表示不再按照scan指定的包掃描,而是按照指定的包掃描,示例:

//注意後面要寫.*當沒有設定use-default-filters屬性或者屬性為true時,表示基于base-packge包下指定掃描的具體路徑

效果相當于:

注意:本人嘗試時無論哪種情況和都不能同時存在

繼續閱讀