Spring Boot2--Web開發(一)
Web開發的核心內容主要包括內嵌Servlet容器和Spring MVC。
Spring Boot提供了spring-boot-starter-web為Web開發予以支援,spring-boot-starter-web為我們提供了嵌入的Tomcat以及Spring MVC的依賴。而Web相關的自動配置儲存在spring-boot-autoconfigure.jar的org.springframework.boot.autoconfigure.web下,如下圖所示:
Spring Boot整合Spring MVC框架並實現自動配置,只需要在pom中新增以下以來即可,不需要其他任何 配置:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
本文中的例子使用了thymeleaf作為模版技術,因此需要新增以下依賴:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Web的模版檔案位於resources/templates目錄下,模版檔案使用的靜態資原始檔,如JS、CSS、圖片,存放在resources/static目錄下。在MVC中,檢視名自動在templates目錄下找到對應的模版名稱,模版中使用的靜態資源將在static目錄下查詢。
Spring MVC框架不像傳統的MVC框架那樣必須繼承某個基礎類才能處理使用者的HTTP請求,Spring MVC只需要在類上宣告@Controller,標註這是一個Controller即可。對於使用者請求,使用@RequestMapping對映HTTP 請求到特定的方法處理類。@RequestMapping既可以作用在方法上,也可以作用在類上。例如:
@Controller
@RequestMapping("/test")
public class HelloworldController {
@RequestMapping("index.html")
public String say(){
return "index.html";
}
}
使用者訪問/test/index.html,則會交給HelloworldController.say方法來處理。say方法返回的型別是字串,預設是檢視名出。Spring Boot的檢視預設儲存在resources/templates目錄下,因此,渲染的檢視是resources/templates/index.html模版檔案。
MVC框架有時候返回的是JSON字串,如果想直接返回內容而不是檢視名,則需要在方法上使用@ResponseBody:
@RequestMapping("index.json")
public @ResponseBody String say(){
return "hello,world";
}
@ResponseBody註解直接將返回的物件輸出到客戶端,如果是字串,則直接返回;如果不是,則預設使用Jackson序列化城JSON字串後輸出。
如果你期望返回JSON,使用了註解@ResponseBody,但你的請求URL以html結尾,這會導致Spring Boot認為請求的是HTML型別的資源,而返回型別是JSON型別資源,與期望型別不一致而報出如下錯誤:
There was an unexpected error (type=Not Acceptable, status=406). Could not find acceptable representation
建議在Spring Boot應用中,如果期望返回JSON,URL請求資源字尾是json;如果期望返回檢視,URL請求資源字尾是html。
@RequestMapping
可以使用@RequestMapping來對映URL,比如/test到某個Controller類,或者是某個具體的方法。通常類上的註解@RequestMapping用來標註請求的路徑,方法上的@RequestMapping註解進一步對映特定的URL到某個具體的處理方法。
@RequestMapping有多個屬性來進一步匹配HTTP請求到Controller方法,分別是:
- value,請求的URL的路徑,支援URL模版、正則表示式。
屬性value用於匹配一個URL對映,value支援簡單的表示式來匹配:
@RequestMapping(value="/get/{id}.json")
public @ResponseBody User getById(@PathVariable("id") Long id){
return userService.getUserById(id);
}
如上面的例子所示,訪問路徑是/get/1.json,將呼叫getById方法,且引數id的值是1。註解@PathVariable作用在方法引數上,用來表示引數的值來自於URL路徑。
如果你的IDE環境啟用了debug模式(通常IDE或者Maven都會啟用),則在編譯Java程式碼稱為位元組碼的時候,方法的引數保留了原來的引數名字。Java8如果使用了parameters編譯選項,也會保留引數名字。Spring可以在這種情況下識別URL中存在的表示式與方法引數的對應關係,從而自動賦值,因此上述程式碼通常可以簡化成:
@RequestMapping(path="/get/{id}.json",method = RequestMethod.GET)
public @ResponseBody User getById(@PathVariable Long id){
return userService.getUserById(id);
}
URL對映也可以使用${}來獲得系統的配置或者環境變數,通常用於Controller路徑是通過配置檔案設定的情況。
@RequestMapping("/${query.all}.json")
public @ResponseBody List<User> getById(){
return userService.allUser();
}
- method,HTTP請求方法,有GET、POST、PUT等。method屬性對映對應HTTP的請求方法,通常HTTP請求方法有如下內容:
GET,用來獲取URL對應的內容。
POST,用來向伺服器提交資訊。
HEAD,同GET,但不返回訊息體,通常用於返回URL對應的元資訊,如過期時間等。
PUT,同POST,用來向伺服器提交資訊,但語義上更像一個更新操作。同一個資料,多次 PUT操作,也不會導致資料發生改變。而POST在語義上更類似新增操作。
DELETE,刪除對應的資源資訊。
PATCH,類似PUT方法,表示資訊的區域性更新。
通常對於Web應用,GET和POST是經常使用的選項,對於REST介面,則會使用PUT、DELETE等用來從語義上進一步區分操作。
Spring提供來簡化後的@RequestMapping,提供了新的註解來表示HTTP方法:
@GetMapping;
@PostMapping;
@PutMapping;
@DeleteMapping;
@PatchMapping;
- consumes,允許的媒體型別(Media Types),如consumes=“application/json”,對應於請求的HTTP的Content-Type。
屬性consumes意味著請求的HTTP頭的Content-Type媒體型別語consumes的值匹配,才能呼叫次方法。
@GetMapping(value="/consumes/test.json",consumes="application/json")
public @ResponseBody User getById(){
return userService.getUserById(1);
}
這裡對映指定請求的媒體型別上application/json,因此,次方法接受一個AJAX請求。如果通過瀏覽器直接訪問,則會看到Spring Boot報出如下錯誤,以為通過瀏覽器訪問,通常並沒有設定Content-Type,所以說null不支援。
- produces,響應的媒體型別,如produces=“application/json”,對應於HTTP的Accept欄位。
produces屬性對應於HTTP請求的Accept欄位,只有匹配得上的方法才能被呼叫。
@GetMapping(path="/user/{userId}",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public @ResponseBody User getUser(@PathVariable Long userId){
return userService.getUserById(userId);
}
通常瀏覽器都會將Accept設定為*.*,因此通過瀏覽器直接訪問/user/1,瀏覽器總是返回id為1的使用者資訊,並轉換成JSON格式。
- params,請求的引數,如params=“action=update”。
- headers,請求的HTTP頭的值,如headers=“myHeader=myValue”
方法引數
Spring的Controller方法可以接受多種型別的引數,比如我們看到的path變數,還有MVC的Model。除此之外,方法還能接受一下引數:
@PathVariable |
可以將URL中的值對映到方法引數中。 |
Model |
Spring中通用的MVC模型,也可以使用Map和ModelMap作為渲染檢視的模型。 |
ModelAndView |
包含了模型和檢視路徑的物件。 |
JavaBean |
將HTTP引數對映到JavaBean物件。 |
MultipartFile |
用於處理檔案上傳。 |
@ModelAttribute |
使用該註解的變數將作為Model的一個屬性。 |
WebRequest或者NativeWebRequest |
類似Servlet Request,但做了一定封裝。 |
java.io.InputStream和java.io.Reader |
用來獲取Servlet API中的InputStream/Reader。 |
java.io.OutputStream/java.io.Writer |
用來獲取Servlet API中的OutputStream/Writer。 |
HttpMethod |
列舉型別,對應於HTTP Method,如POST、GET。 |
@MatrixVariable |
矩陣變數。 |
@RequestParam |
對應於HTTP請求的引數,自動轉化為引數對應的型別。 |
@RequestHeader |
對應於HTTP請求頭引數,自動轉化為對應的型別。 |
@RequestBody |
自動將請求內容轉為指定的物件,預設使用HttpMessageConverters來轉換。 |
@RequestPart |
用於檔案上傳,對應於HTTP請求的multipart/form-data。 |
@SessionAttribute |
該方法標註的變數來自於Session的屬性。 |
@RequestAttribute |
該標註的變數來自於request的屬性。 |
@InitBinder |
用在方法上,說明這個方法會註冊多個轉化器,用來個性化地將HTTP請求引數轉化成對應的Java物件,如轉化為日期型別、浮點型別、JavaBean等,當然,也可以實現WebBindingInitializer介面來用於Spring Boot應用所需要的dataBinder。 |
BindingResult和Errors |
用來處理繫結過程中的錯誤。 |