6.1、註解式控制器簡介
一、Spring2.5之前,我們都是通過實現Controller接口或其實現來定義我們的處理器類。已經@Deprecated。
二、Spring2.5引入註解式處理器支持,通過@Controller 和 @RequestMapping註解定義我們的處理器類。並且提供了一組強大的註解:
需要通過處理器映射DefaultAnnotationHandlerMapping和處理器適配器AnnotationMethodHandlerAdapter來開啓支持@Controller 和 @RequestMapping註解的處理器。
@Controller:
用於標識是處理器類;
@RequestMapping:
請求到處理器功能方法的映射規則;
@RequestParam:
請求參數到處理器功能處理方法的方法參數上的綁定;
@ModelAttribute:
請求參數到命令對象的綁定;
@SessionAttributes:
用於聲明session級別存儲的屬性,放置在處理器類上,通常列出模型屬性(如@ModelAttribute)對應的名稱,則這些屬性會透明的保存到session中;
@InitBinder:
自定義數據綁定註冊支持,用於將請求參數轉換到命令對象屬性的對應類型;
三、Spring3.0引入RESTful架構風格支持(通過@PathVariable註解和一些其他特性支持),且又引入了更多的註解支持:
@CookieValue:
cookie數據到處理器功能處理方法的方法參數上的綁定;
@RequestHeader:
請求頭(header)數據到處理器功能處理方法的方法參數上的綁定;
@RequestBody:
請求的body體的綁定(通過HttpMessageConverter進行類型轉換);
@ResponseBody:
處理器功能處理方法的返回值作爲響應體(通過HttpMessageConverter進行類型轉換);
@ResponseStatus:
定義處理器功能處理方法/異常處理器返回的狀態碼和原因;
@ExceptionHandler:
註解式聲明異常處理器;
@PathVariable:
請求URI中的模板變量部分到處理器功能處理方法的方法參數上的綁定,從而支持RESTful架構風格的URI;
四、Spring3.1使用新的HandlerMapping 和 HandlerAdapter來支持@Contoller和@RequestMapping註解處理器。
新的@Contoller和@RequestMapping註解支持類:處理器映射RequestMappingHandlerMapping 和 處理器適配器RequestMappingHandlerAdapter組合來代替Spring2.5開始的處理器映射DefaultAnnotationHandlerMapping和處理器適配器AnnotationMethodHandlerAdapter,提供更多的擴展點。
接下來,我們一起開始學習基於註解的控制器吧。
6.2、入門
(1、控制器實現
package cn.javass.chapter6.web.controller;
//省略import
@Controller // 或 @RequestMapping //①將一個POJO類聲明爲處理器
public class HelloWorldController {
@RequestMapping(value = "/hello") //②請求URL到處理器功能處理方法的映射
public ModelAndView helloWorld() {
//1、收集參數
//2、綁定參數到命令對象
//3、調用業務對象
//4、選擇下一個頁面
ModelAndView mv = new ModelAndView();
//添加模型數據 可以是任意的POJO對象
mv.addObject("message", "Hello World!");
//設置邏輯視圖名,視圖解析器會根據該名字解析到具體的視圖頁面
mv.setViewName("hello");
return mv; //○3 模型數據和邏輯視圖名
}
}
1
可以通過在一個POJO類上放置@Controller或@RequestMapping,即可把一個POJO類變身爲處理器;
2
@RequestMapping(value = "/hello")
請求URL(/hello) 到 處理器的功能處理方法的映射;
3
模型數據和邏輯視圖名的返回。
現在的處理器無需實現/繼承任何接口/類,只需要在相應的類/方法上放置相應的註解說明下即可,非常方便。
(2、Spring配置文件chapter6-servlet.xml
(2.1、HandlerMapping和HandlerAdapter的配置
如果您使用的是Spring3.1之前版本,開啓註解式處理器支持的配置爲:DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter。
<!—Spring3.1之前的註解 HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
<!—Spring3.1之前的註解 HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
如果您使用的Spring3.1開始的版本,建議使用RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
<!--Spring3.1開始的註解 HandlerMapping -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
<!--Spring3.1開始的註解 HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
下一章我們介紹DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter 與RequestMappingHandlerMapping和RequestMappingHandlerAdapter 的區別。
(2.2、視圖解析器的配置
還是使用之前的org.springframework.web.servlet.view.InternalResourceViewResolver。
(2.3、處理器的配置
<!-- 處理器 -->
<bean class="cn.javass.chapter6.web.controller.HelloWorldController"/>
只需要將處理器實現類註冊到spring配置文件即可,spring的DefaultAnnotationHandlerMapping或RequestMappingHandlerMapping能根據註解@Controller或@RequestMapping自動發現。
(2.3、視圖頁面(/WEB-INF/jsp/hello.jsp)
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
${message}
</body>
</html>
${message}:表示顯示由HelloWorldController處理器傳過來的模型數據。
(4、啓動服務器測試
地址欄輸入http://localhost:9080/springmvc-chapter6/hello,我們將看到頁面顯示“Hello World!”,表示成功了。
整個過程和我們第二章中的Hello World 類似,只是處理器的實現不一樣。接下來我們來看一下具體流程吧。
6.3、運行流程
和第二章唯一不同的兩處是:
1、HandlerMapping實現:使用DefaultAnnotationHandlerMapping(spring3.1之前)或RequestMappingHandlerMapping(spring3.1)
替換之前的BeanNameUrlHandlerMapping。
註解式處理器映射會掃描spring容器中的bean,發現bean實現類上擁有@Controller或@RequestMapping註解的bean,並將它們作爲處理器。
2、HandlerAdapter實現:使用AnnotationMeth
odHandlerAdapter(spring3.1之前)或RequestMappingHandlerAdapter(spring3.1)替換之前的SimpleControllerHandlerAdapter。
註解式處理器適配器會通過反射調用相應的功能處理方法(方法上擁有@RequestMapping註解
)。
好了到此我們知道Spring如何發現處理器、如何調用處理的功能處理方法了,接下來我們詳細學習下如何定義處理器、如何進行請求到功能處理方法的定義。
6.4、處理器定義
6.4.1、@Controller
@Controller
public class HelloWorldController {
……
}
推薦使用這種方式聲明處理器,它和我們的@Service、@Repository很好的對應了我們常見的三層開發架構的組件。
6.4.2、@RequestMapping
@Controller
public class HelloWorldController {
……
}
這種方式也是可以工作的,但如果在類上使用@ RequestMapping註解一般是用於窄化功能處理方法的映射的,詳見6.4.3。
package cn.javass.chapter6.web.controller;
@Controller
@RequestMapping(value="/user") //①處理器的通用映射前綴
public class HelloWorldController2 {
@RequestMapping(value = "/hello2") //②相對於①處的映射進行窄化
public ModelAndView helloWorld() {
//省略實現
}
}
6.4.3、窄化請求映射
package cn.javass.chapter6.web.controller;
@Controller
@RequestMapping(value="/user") //①處理器的通用映射前綴
public class HelloWorldController2 {
@RequestMapping(value = "/hello2") //②相對於①處的映射進行窄化
public ModelAndView helloWorld() {
//省略實現
}
}
①類上的@RequestMapping(value="/user") 表示處理器的通用請求前綴;
②處理器功能處理方法上的是對①處映射的窄化。
因此http://localhost:9080/springmvc-chapter6/hello2 無法映射到HelloWorldController2的 helloWorld功能處理方法;而http://localhost:9080/springmvc-chapter6/user/hello2是可以的。
窄化請求映射可以認爲是方法級別的@RequestMapping繼承類級別的@RequestMapping。
窄化請求映射還有其他方式,如在類級別指定URL,而方法級別指定請求方法類型或參數等等,後續會詳細介紹。
到此,我們知道如何定義處理器了,接下來我們需要學習如何把請求映射到相應的功能處理方法進行請求處理。
6.5、請求映射
處理器定義好了,那接下來我們應該定義功能處理方法,接收用戶請求處理並選擇視圖進行渲染。首先我們看一下圖6-1:
http請求信息包含六部分信息:
①請求方法,如GET或POST,表示提交的方式;
②URL,請求的地址信息;
③協議及版本;
④請求頭信息(包括Cookie信息);
⑤回車換行(CRLF);
⑥請求內容區(即請求的內容或數據),如表單提交時的參數數據、URL請求參數(?abc=123 ?後邊的)等。
想要了解HTTP/1.1協議,請訪問http://tools.ietf.org/html/rfc2616。
那此處我們可以看到有①、②、④、⑥一般是可變的,因此我們可以這些信息進行請求到處理器的功能處理方法的映射,因此請求的映射分爲如下幾種:
URL路徑映射:使用URL映射請求到處理器的功能處理方法;
請求方法映射限定:如限定功能處理方法只處理GET請求;
請求參數映射限定:如限定只處理包含“abc”請求參數的請求;
請求頭映射限定:如限定只處理“Accept=application/json”的請求。
接下來看看具體如何映射吧。