轉自http://www.cnblogs.com/leskang/p/5445698.html
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 控制器。
<!--方式一--> <bean class="com.host.app.web.controller.MyController"/> <!--方式二--> < 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 { @Autowired @Qualifier("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
用於在 請求的 / 后面傳遞參數
<h1>pathVariable參數傳遞</h1> <a href="test2/dhb">參數傳遞</a><br> @RequestMapping("/test1") //傳遞參數 public String test1(@RequestParam("param")String str){ System.out.println(str); return "1"; //跳轉的頁面 }
6、@requestParam
@requestParam主要用於在SpringMVC后台控制層獲取參數,類似一種是request.getParameter("name"),它有三個常用參數:defaultValue = "0", required = false, value = "isApp";defaultValue 表示設置默認值,required 銅過boolean設置是否是必須要傳入的參數,value 值表示接受的傳入的參數類型。
<h1>參數傳遞</h1> <a href="test1?param=hanqi">參數傳遞</a><br> @RequestMapping("/test1") //傳遞參數 public String test1(@RequestParam("param")String str){ System.out.println(str); return "1"; //跳轉的頁面 }
7、@ResponseBody
作用: 該注解用於將Controller的方法返回的對象,通過適當的HttpMessageConverter轉換為指定格式后,寫入到Response對象的body數據區。
使用時機:返回的數據不是html標簽的頁面,而是其他某種格式的數據時(如json、xml等)使用;
$("#btn").click(function(){ var f = $("#forms").serializeArray(); $.ajax({ url:"test3.do", data:f, type:"post", dataType:"json", success:function(data){ console.log(data.success); if(data.success){ alert("成功"); }else{ $("#forms").find("span").show(); } } }) }) @ResponseBody @RequestMapping("/test3.do") public String test3(AppUser user){ String result = ""; System.out.println(user); if(user.getUsername().equals("dhb")&&user.getPassword().equals("123")){ result = "{\"success\":true}"; }else{ result = "{\"success\":false}"; } return result; //把數據返回 }
8、@Component
相當於通用的注解,當不知道一些類歸到哪個層時使用,但是不建議。
9、@Repository
用於注解dao層,在daoImpl類上面注解。
注:
1、使用 @RequestMapping 來映射 Request 請求與處理器
方式一、通過常見的類路徑和方法路徑結合訪問controller方法
方式二、使用uri模板
@Controller @RequestMapping ( "/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; } }
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 中還是存放在模型中,我們來做一個實驗,看下面一段代碼。
@SessionAttributes("user1") @RequestMapping("/test4.do") public String test4(AppUser user,Model model){ System.out.println(user); model.addAttribute("user1",user); return "1"; }
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 } }
(2)、@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<String, String>里,這種情況在某些特殊需求下使用,詳情查看FormHttpMessageConverter api;
示例代碼:
@RequestMapping(value = "/something", method = RequestMethod.PUT) public void handle(@RequestBody String body, Writer writer) throws IOException { writer.write(body); }
(3)、@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); }