1. 程式人生 > >Spring Boot2--Web開發(一)

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

用來處理繫結過程中的錯誤。