Spring、SpringMVC中常用註解含義及用法

1、@Controller

在SpringMVC中只需要使用這個標記一個類是Controller,然後使用@RequestMapping和@RequestParam等一些註解用以定義URL請求和Controller方法之間的映射,這樣的Controller就能被外界訪問到。此外,Controller不會直接依賴於HttpServletRequest 和HttpServletResponse 等HttpServlet 對象,他們可以通過Controller的方法參數靈活的獲取到。

舉個例子:

  1. @Controller
  2. public class TestController {
  3. @RequestMapping ( "/showView" )
  4. public ModelAndView showView() {
  5. ModelAndView modelAndView = new ModelAndView();
  6. modelAndView.setViewName( "viewName" );
  7. modelAndView.addObject( " 需要放到 model 中的屬性名稱 " , " 對應的屬性值,它是一個對象 " );
  8. return modelAndView;
  9. }
  10. }

在上面的例子中,@Controller是標記在類TestController上面的, 所以類TestController就是一個SpringMVC Controller對象。分發處理器會掃描使用了該註解的類的方法,並檢測該方法是否調用了@RequestMapping註解。@Controller只是定義了一個控制器類,而使用@RequestMapping註解的方法纔是真正處理請求的處理器。然後使用@RequestMapping ( "/showView" )標記在Controller方法上,表示當請求/showView.do 的時候訪問的是TestController 的showView 方法,該方法返回了一個包括Model 和View 的ModelAndView 對象。

單單使用@Controller 標記在一個類上還不能真正意義上的說它就是SpringMVC 的一個控制器類,因爲這個時候Spring 還不認識它。那麼要如何做Spring 才能認識它呢?這個時候就需要把這個控制器類交給Spring 來管理。

第一種方式是在SpringMVC 的配置文件中定義MyController 的bean 對象。

第二種方式是在SpringMVC 的配置文件中告訴Spring 該到哪裏去找標記爲@Controller 的Controller 控制器。

  1. < context:component-scan base-package = "com.host.app.web.controller" >
  2. < context:exclude-filter type = "annotation"
  3. expression = "org.springframework.stereotype.Service" />
  4. context:component-scan >

注:上面 context:exclude-filter 標註的是不掃描 @Service 標註的類

2、@RequestMapping

使用 @RequestMapping 來映射 Request 請求與處理器,通過這個註解可以定義不同的處理器映射規則,即爲控制器指定可以處理哪些URL請求。

用@RequestMapping 來映射URL 到控制器類,或者是到Controller 控制器的處理方法上。當@RequestMapping 標記在Controller 類上的時候,裏面使用@RequestMapping 標記的方法的請求地址都是相對於類上的@RequestMapping 而言的;當Controller 類上沒有標記@RequestMapping 註解時,方法上的@RequestMapping 都是絕對路徑。這種絕對路徑和相對路徑所組合成的最終路徑都是相對於根路徑“/ ”而言的。

在上面那個例子中:

這個控制器裏因爲TestController 沒有被@RequestMapping 標記,所以當需要訪問到裏面使用了@RequestMapping 標記的showView 方法時,就是使用的絕對路徑/showView.do 請求就可以了。

如果改成這樣:

  1. @Controller
  2. @RequestMapping ( "/test" )
  3. public class TestController {
  4. @RequestMapping ( "/showView" )
  5. public ModelAndView showView() {
  6. ModelAndView modelAndView = new ModelAndView();
  7. modelAndView.setViewName( "viewName" );
  8. modelAndView.addObject( " 需要放到 model 中的屬性名稱 " , " 對應的屬性值,它是一個對象 " );
  9. return modelAndView;
  10. }
  11. }

這種情況下是在控制器上加了@RequestMapping 註解,所以當需要訪問到裏面使用了@RequestMapping 標記的方法showView() 的時候就需要使用showView 方法上@RequestMapping 相對於控制器TestController上@RequestMapping 的地址,即/test/showView.do 。


URL路徑映射:@RequestMapping("/hello"),可以將多個url映射到同一個方法上。

窄化請求映射:

(1)在class上面添加@RequestMapping(url)指定通用請求前綴,限制此類下的所有方法請求url必須以請求前綴開頭,通過此方法來分類管理url;

(2)在方法名上面再設置請求映射url,即添加@RequestMapping註解在方法名上。return “/WEB-INF/jsp/login.jsp” 調用這個方法,重定向的到指定的jsp頁面或制定的@RequestMapping的請求路徑;

(3)在瀏覽器上輸入相應地址,完成訪問。

3、@RequestBody

用於讀取http請求的內容(字符串),通過springMVC提供的HttpMessageConverter接口將讀取到的內容轉換爲json、xml等格式的數據,再轉換爲java對象綁定到Controller類方法的參數上。

簡單點來說,就是把json格式的數據轉換爲java對象,就舉個例子來說明:

編寫一個jsp頁面來向後臺傳遞json格式的數據(切記是json格式的):

  1. jsonData();
  2. function jsonData()
  3. {
  4. $.ajax({
  5. url:"/user/jsonTest.do",
  6. contentType:'application/json;charset=utf-8',//設置json格式
  7. data:'{"username":"張三":"address":"福州"}',
  8. type:'post',
  9. success:function(data){
  10. alert(data);
  11. },error:function(error){
  12. alert(error);
  13. }
  14. })
  15. }

然後在後臺接收一下:

  1. @RequestMapping("/jsonTest.do")
  2. public void jsonTest(@RequestBody User user) throws Exception
  3. {
  4. System.out.println(user.toString());
  5. }

這樣的話,前臺的兩個json數據就會自動匹配到User這個對象的屬性中了,當然屬性名稱要一樣的。

查看一下結果:

Spring、SpringMVC中常用註解含義及用法

可以看到User這個對象中的username和address都已經自動賦值好了,這個就是json格式的數據轉java對象了,可以省去我們在後臺將json轉成java對象。不過在使用的時候,要注意兩邊的名稱要相同,前臺的username要對應java對象中的username這樣才能成功。否則得到如下:

Spring、SpringMVC中常用註解含義及用法

4、@ResponseBody

含義:

@Responsebody 註解表示該方法的返回的結果直接寫入 HTTP 響應正文(ResponseBody)中,一般在異步獲取數據時使用,通常是在使用 @RequestMapping 後,返回值通常解析爲跳轉路徑,加上 @Responsebody 後返回結果不會被解析爲跳轉路徑,而是直接寫入HTTP 響應正文中。

作用:

用於將Controller中方法返回的對象通過適當的HttpMessageConverter轉換爲指定格式的數據,如:json、xml等,然後寫入到response對象的body區,通過Response響應給客戶端。需要注意的是,在使用此註解之後不會再走試圖處理器,而是直接將數據寫入到輸入流中,他的效果等同於通過response對象輸出指定格式的數據。

使用時機:

返回的數據不是html標籤的頁面,而是其他某種格式的數據時(如json、xml等)使用;

舉個例子:

  1.   @RequestMapping("/login")
  2.   @ResponseBody
  3.   public User login(User user){
  4.     return user;
  5.   }

User字段是:userName pwd

那麼在前臺接收到的數據爲:'{"userName":"xxx","pwd":"xxx"}'

效果等同於如下代碼:

  1.   @RequestMapping("/login")
  2.   public void login(User user, HttpServletResponse response){
  3.     response.getWriter.write(JSONObject.fromObject(user).toString());
  4.   }

5、@ModelAttribute

在方法定義上使用該註解: SpringMVC在調用目標處理方法前, 會先逐個調用在方法級上標註了@ModelAttribute的方法;

在方法的入參前使用該註解:可以從隱含對象中獲取隱含的模型數據中獲取對象,再將請求參數 –綁定到對象中,再傳入入參將方法入參對象添加到模型中。

6、@RequestParam

處理簡單類型的綁定,用 @RequestParam 綁定 HttpServletRequest 請求參數到控制器方法參數,即在處理方法入參處使用該註解,可以把請求參數傳遞給請求方法。

  1. @RequestMapping ( "requestParam" )
  2. public String testRequestParam( @RequestParam(required=false) String name, @RequestParam ( "age" ) int age) {
  3. return "requestParam" ;
  4. }

在上面代碼中利用@RequestParam 從HttpServletRequest 中綁定了參數name 到控制器方法參數name ,綁定了參數age 到控制器方法參數age 。當沒有明確指定從request 中取哪個參數時,Spring 在代碼是debug 編譯的情況下會默認取跟方法參數同名的參數,如果不是debug 編譯的就會報錯。此外,當需要從request 中綁定的參數和方法的參數名不相同的時候,也需要在@RequestParam 中明確指出是要綁定哪個參數。在上面的代碼中如果訪問 /requestParam.do?name=hello&age=1 則Spring 將會把request請求參數name的值hello賦給對應的處理方法參數name ,把參數age 的值1 賦給對應的處理方法參數age 。

在@RequestParam 中除了指定綁定哪個參數的屬性value之外,還有一個屬性required,它表示所指定的參數是否必須在request 屬性中存在,默認是true,表示必須存在,當不存在時就會報錯。在上面代碼中我們指定了參數name的required的屬性爲false ,而沒有指定age 的required 屬性,這時候如果我們訪問/requestParam.do而沒有傳遞參數的時候,系統就會拋出異常,因爲age 參數是必須存在的,而我們沒有指定。而如果我們訪問 /requestParam.do?age=1 的時候就可以正常訪問,因爲我們傳遞了必須的參數age ,而參數name是非必須的,不傳遞也可以。

value:參數名,即入參的請求參數名字

如:value="id",表示將請求的參數區的名字爲id的參數的值等待傳入;

require:是否必需,默認是true,表示請求中一定要有相應的參數,否則會報400錯誤。且在每個參數定義前設置。

defaultValue:默認值,表示如果請求中沒有同名參數時的默認值。


通過 require=true 限定參數id必須傳遞,如果不傳遞會報400錯誤;

可以使用defaultValue設置默認值,即使 require=true 也可以不傳遞id參數。

7、@PathVariable 綁定URL佔位符到入參。

8、@ExceptionHandler 註解到方法上, 出現異常時會執行該方法。

9、@ControllerAdvice 使一個Controller成爲全局的異常處理類, 類中用ExceptinHandler方法註解的方法可以處理所有Controller發生的異常。

10、@Autowired

它可以對類成員變量、方法以及構造函數進行標註,完成自動裝配的工作。通過@Autowired 的使用來消除代碼Java代碼裏面的getter/setter與bean屬性中的property。當然,getter看個人需求,如果私有屬性需要對外提供的話,應當予以保留。

@Autowired 和 @Service("")的配合使用:

實例:


  1. @Controller
  2. @RequestMapping("/test")
  3. public class StudentController {
  4. @Autowired
  5. private StudentService studentService;
  6. @RequestMapping("getInfo")
  7. @ResponseBody
  8. public int getInfo(Student student){
  9. return studentService.insertStu(student);
  10. }
  11. }

在Controller中對私有變量用@Autowired標註,因爲studentService這個變量是service層接口,所以要找到他的實現類StudentServiceImpl,並在實現類上添加@Service("")的註釋。

  1. @Service("StudentService")
  2. public class StudentServiceImpl implements StudentService {
  3. @Autowired
  4. private StudentDao studentDao;
  5. public int insertStu(Student student){
  6. return studentDao.insertInfo(student);
  7. }
  8. }

如果不添加@Service("")註釋,會報如下錯誤。因爲@Autowired 將尋找與之匹配的bean來創建(類名)bena,但因爲刪除接口實現類上@Service("")註解,找不到服務對象,@Autowired自然也就找不到實例bean了。

Spring、SpringMVC中常用註解含義及用法

11、@Override

@Override是僞代碼,表示重寫(當然不寫也可以),不過也有好處:

(1)可以當註釋用,方便閱讀;

(2)編譯器可以給你驗證@Override下面的方法名是否是你父類中所有的,如果沒有則報錯。

例如,你如果沒寫@Override,而你下面的方法名又寫錯了,這時你的編譯器是可以編譯通過的,因爲編譯器以爲這個方法是你的子類中自己增加的方法。

舉例:在重寫父類的onCreate時,在方法前面加上@Override 系統可以幫你檢查方法的正確性。

@Override

public void onCreate(Bundle savedInstanceState)

{…….}

這種寫法是正確的,如果你寫成:

@Override

public void oncreate(Bundle savedInstanceState)

{…….}

編譯器會報如下錯誤:

The method oncreate(Bundle) of type HelloWorld must override or implement a supertype method,以確保你正確重寫onCreate方法(因爲oncreate應該爲onCreate)。

而如果你不加@Override,則編譯器將不會檢測出錯誤,而是會認爲你爲子類定義了一個新方法:oncreate

12、@Transactional

使用時機:

對數據庫的數據進行批量或連表操作時,爲了保證數據的一致性和正確性,則需要添加事務管理機制進行管理;

當對數據庫的數據操作失敗時,事務管理可以很好保證所有的數據 回滾 到原來的數據,如果操作成功,則保證所有的需要更新的數據持久化。

回滾(Rollback)指的是程序或數據處理錯誤,將程序或數據恢復到上一次正確狀態的行爲。

回滾包括程序回滾和數據回滾等類型。

刪除由一個或多個部分完成的事務執行的更新。爲保證應用程序、數據庫或系統錯誤後還原數據庫的完整性,需要使用回滾。

回滾泛指程序更新失敗, 返回上一次正確狀態的行爲。

回滾與恢復有本質的區別。

升級回滾:是指因升級中所發生的意外而自動回滾。

使用優點:

(1)開發團隊達成一致約定,明確標註事務方法的編程風格;

(2)保證事務方法的執行時間儘可能短,不要穿插其他網絡操作,RPC/HTTP請求或者剝離到事務方法外部;

(3)不是所有的方法都需要事務,如果只有一條修改操作、只讀操作不需要事務控制。

13、@Param

mybatis提供了一個使用註解來參入多個參數的方法,這種方法需要在接口的參數上添加@Param註解。

舉個例子:

  1. /**
  2. * 更新學生信息
  3. * @param student
  4. * @return
  5. */
  6. int updateInfo(@Param("student") Student student);

在這個updateInfo的方法中需要傳入多個參數,那麼在進行mybatis配置的時候,沒有辦法同事配置多個參數,所以需要@Param這個註解來綁定參數對象。student這個參數中包含了三個對象,用@Param來綁定參數並命名爲"student"。並且在mapper.xml文件中調用時,對逐個參數在調用時,要加上 student. 的前綴。如下所示:

  1. UPDATE test_student SET name=#{student.name},age=#{student.age} WHERE id=#{student.id}

注意事項:在使用@Param來註解時,如果使用#{ } 或者 ${ } 的方式都可以,但如果不是用@Param註解時,則必須使用#{ }方式。


@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用來指示參數是否必須綁定。

在方法參數裏面如是:

  1. public WebResponse findReleventPolicyPage(@RequestParam("pageSize") Integer pageSize,
  2. @RequestParam("pageNum") Integer pageNum,
  3. @RequestParam("type") Integer type){}

@RequestBody

處理HttpEntity傳遞過來的數據,一般用來處理非Content-Type: application/x-www-form-urlencoded編碼格式的數據。

GET請求中,因爲沒有HttpEntity,所以@RequestBody並不適用。

POST請求中,通過HttpEntity傳遞的參數,必須要在請求頭中聲明數據的類型Content-Type,SpringMVC通過使用HandlerAdapter 配置的HttpMessageConverters來解析HttpEntity中的數據,然後綁定到相應的bean上。

用於將Controller中方法返回的對象,通過適當的HttpMessageConverter轉換爲指定格式的數據,如:json、xml等,然後通過Response響應給客戶端。

在方法參數裏面如是:

  1. @RequestMapping("/json_test")
  2. // 響應json數據,把pojo對象轉換成json數據並響應
  3. @ResponseBody
  4. public Items jsonTest (@RequestBody Items items){ // 接受json數據並轉換成pojo對象
  5. return items;
  6. }

總結

在GET請求中,不能使用@RequestBody。

在POST請求,可以使用@RequestBody和@RequestParam,但是如果使用@RequestBody,對於參數轉化的配置必須統一。

舉個例子,在SpringMVC配置了HttpMessageConverters處理棧中,指定json轉化的格式,如Date轉成‘yyyy-MM-dd’,則參數接收對象包含的字段如果是Date類型,就只能讓客戶端傳遞年月日的格式,不能傳時分秒。因爲不同的接口,它的參數可能對時間參數有不同的格式要求,所以這樣做會讓客戶端調用同事對參數的格式有點困惑,所以說擴展性不高。

如果使用@RequestParam來接受參數,可以在接受參數的model中設置@DateFormat指定所需要接受時間參數的格式。

另外,使用@RequestBody接受的參數是不會被Servlet轉化統一放在request對象的Param參數集中,@RequestParam是可以的。

綜上所述,一般情況下,推薦使用@RequestParam註解來接受Http請求參數。

相关文章