Spring Boot Web 開(kāi)發(fā)注解篇
本文提綱
- 1. spring-boot-starter-web 依賴概述
- 1.1 spring-boot-starter-web 職責(zé)
- 1.2 spring-boot-starter-web 依賴關(guān)系
- 2. Spring MVC on Spring Boot
- 2.1 Spring MVC 體系溫故知新
- 2.2 重要的類
- 2.3 Spring Boot MVC
- 2.3.1 控制器
- 2.3.2 數(shù)據(jù)綁定
- 2.3.3 視圖和視圖解析
spring-boot-starter-web
在 Spring Boot 快速入門中,只要在 pom.xml 加入了 spring-boot-starter-web 依賴,即可快速開(kāi)發(fā) web 應(yīng)用??梢?jiàn),Spring Boot 極大地簡(jiǎn)化了 Spring 應(yīng)用從搭建到開(kāi)發(fā)的過(guò)程,做到了「開(kāi)箱即用」的方式。Spring Boot 已經(jīng)提供很多「開(kāi)箱即用」的依賴,如上面開(kāi)發(fā) web 應(yīng)用使用的 spring-boot-starter-web ,都是以 spring-boot-starter-xx 進(jìn)行命名的。
Spring Boot 「開(kāi)箱即用」 的設(shè)計(jì),對(duì)開(kāi)發(fā)者非常便利。簡(jiǎn)單來(lái)說(shuō),只要往 Spring Boot 項(xiàng)目加入相應(yīng)的 spring-boot-starter-xx 依賴,就可以使用對(duì)應(yīng)依賴的功能,比如加入 spring-boot-starter-data-jpa 依賴,就可以使用數(shù)據(jù)持久層框架 Spring Data JPA 操作數(shù)據(jù)源。相比 Spring 以前需要大量的XML配置以及復(fù)雜的依賴管理,極大的減少了開(kāi)發(fā)工作量和學(xué)習(xí)成本。
當(dāng)開(kāi)發(fā)一個(gè)特定類型的應(yīng)用程序時(shí),特定的 Starter 提供所需的依賴關(guān)系,并且將對(duì)應(yīng)的 Bean 注冊(cè)到 Spring 容器中。spring-boot-starter-web 依賴就是提供開(kāi)發(fā) Web 應(yīng)用的。
1.1 spring-boot-starter-web 職責(zé)
spring-boot-starter-web 是一個(gè)用于構(gòu)建 Web 的 Starter ,包括構(gòu)建 RESTful 服務(wù)應(yīng)用、Spring MVC 應(yīng)用等。并且不需要額外配置容器,默認(rèn)使用 Tomcat 作為嵌入式容器。
1.2 spring-boot-starter-web 依賴關(guān)系
spring-boot-starter-web 這么強(qiáng)大,它的組成如下表:
spring-boot-starter 核心包,包括了自動(dòng)化配置支持、日志、YAML 文件解析的支持等。
spring-boot-starter-json 讀寫 JSON 包
spring-boot-starter-tomcat Tomcat 嵌入式 Servlet 容器包
hibernate-validator Hibernate 框架提供的驗(yàn)證包
spring-web Spring 框架的 Web 包
spring-webmvc Spring 框架的 Web MVC 包
spring-boot-starter-web 包含了 Tomcat 和 Spring MVC ,那啟動(dòng)流程是這樣的。 標(biāo)識(shí) @SpringBootApplication 的應(yīng)用,初始化經(jīng)過(guò) spring-boot-starter 核心包中的自動(dòng)化配置,構(gòu)建了 Spring 容器,并通過(guò) Tomcat 啟動(dòng) Web 應(yīng)用。很多 Starters 只支持 Spring MVC,一般會(huì)將 spring-boot-starter-web 依賴加入到應(yīng)用的 Classpath。
另外,spring-boot-starter-web 默認(rèn)使用 Tomcat 作為嵌入式 Servlet 容器,在 pom.xml 配置 spring-boot-starter-jetty 和 spring-boot-starter-undertow 就可以替換默認(rèn)容器。
Spring MVC on Spring Boot
Spring MVC 是 Spring Web 重要的模塊。內(nèi)容包括 MVC 模式的實(shí)現(xiàn)和 RESTful 服務(wù)的支持。
2.1 Spring MVC 體系溫故知新
spring-webmvc 模塊里面包:
- org.springframework.web.servlet 提供與應(yīng)用程序上下文基礎(chǔ)結(jié)構(gòu)集成的 Servlet,以及 Spring web MVC 框架的核心接口和類。
- org.springframework.web.servlet.mvc Spring 附帶的 Servlet MVC 框架的標(biāo)準(zhǔn)控制器實(shí)現(xiàn)。
- org.springframework.web.servlet.mvc.annotation 用于基于注解的 Servlet MVC 控制器的支持包。
- org.springframework.web.servlet.mvc.condition 用于根據(jù)條件匹配傳入請(qǐng)求的公共 MVC 邏輯。
- org.springframework.web.servlet.mvc.method 用于處理程序方法處理的基于 Servlet 的基礎(chǔ)結(jié)構(gòu),基于在 org.springframework.web.method 包上。
- org.springframework.web.servlet.view 提供標(biāo)準(zhǔn)的 View 和 ViewResolver 實(shí)現(xiàn),包括自定義實(shí)現(xiàn)的抽象基類。
- org.springframework.web.servlet.view.freemarker 支持將 FreeMarker 集成為 Spring Web 視圖技術(shù)的類。
- org.springframework.web.servlet.view.json 支持提供基于 JSON 序列化的 View 實(shí)現(xiàn)的類。
上面列出來(lái)核心的包。org.springframework.web.servlet.view 包中, View 視圖實(shí)現(xiàn)有常見(jiàn)的:JSON 、FreeMarker 等。org.springframework.web.servlet.mvc 包中,Controller 控制層實(shí)現(xiàn)包括了注解、程序方法處理等封裝。自然,看源碼先從 org.springframework.web.servlet 包看其核心的接口和類。
2.2 重要的類
DispatcherServlet 類:調(diào)度 HTTP 請(qǐng)求控制器(或者處理器 Handler)。
View 視圖層 ModelAndView 類:模型和視圖的持有者。
View 接口:MVC WEB 交互。該接口的實(shí)現(xiàn)負(fù)責(zé)呈現(xiàn)視圖或者暴露模型。
Controller 控制層 HandlerMapping 接口: 請(qǐng)求從 DispacherServlet 過(guò)來(lái),該接口定義請(qǐng)求和處理程序?qū)ο笾g的映射。
HandlerInterceptor 接口:處理程序的執(zhí)行鏈接口。
Spring MVC 框架模型
2.3 Spring Boot MVC
以前 Spring MVC 開(kāi)發(fā)模式是這樣的:
1. 在 web.xml 配置 DispatcherServlet,用于截獲并處理所有請(qǐng)求
2. 在 Spring MVC 配置文件中,聲明預(yù)定義的控制器和視圖解析器等
3. 編寫預(yù)定義的處理請(qǐng)求控制器
4. 編寫預(yù)定義的視圖對(duì)象,比如 JSP、Freemarker 等
在 Spring Boot MVC 中,Web 自動(dòng)化配置會(huì)幫你減少上面的兩個(gè)步驟。默認(rèn)使用的視圖是 ThymeLeaf,在下面小節(jié)會(huì)具體講
1. 編寫預(yù)定義的處理請(qǐng)求控制器
2. 編寫默認(rèn) ThymeLeaf 視圖對(duì)象
例如下面會(huì)展示用戶列表案例:
***步:處理用戶請(qǐng)求控制器
UserController.java
- /**
- * 用戶控制層
- *
- * Created by bysocket on 24/07/2017.
- */
- @Controller
- @RequestMapping(value = "/users") // 通過(guò)這里配置使下面的映射都在 /users
- public class UserController {
- @Autowired
- UserService userService; // 用戶服務(wù)層
- /**
- * 獲取用戶列表
- * 處理 "/users" 的GET請(qǐng)求,用來(lái)獲取用戶列表
- * 通過(guò) @RequestParam 傳遞參數(shù),進(jìn)一步實(shí)現(xiàn)條件查詢或者分頁(yè)查詢
- */
- @RequestMapping(method = RequestMethod.GET)
- public String getUserList(ModelMap map) {
- map.addAttribute("userList", userService.findAll());
- return "userList";
- }
- }
@Controller 注解在 UserController 類上,標(biāo)識(shí)其為一個(gè)可接收 HTTP 請(qǐng)求的控制器
@RequestMapping(value = "/users") 注解 ,標(biāo)識(shí) UserController 類下所有接收的請(qǐng)求路由都是 /users 開(kāi)頭的。注意:類上的 @RequestMapping 注解是不必需的
@RequestMapping(method = RequestMethod.GET) 注解,標(biāo)識(shí)該 getUserList(ModelMap map) 方法會(huì)接收并處理 /users 請(qǐng)求,且請(qǐng)求方法是 GET
getUserList(ModelMap map) 方法返回的字符串 userList ,代表著是視圖,會(huì)有視圖解析器解析成為一個(gè)具體的視圖對(duì)象,然后經(jīng)過(guò)視圖渲染展示到瀏覽器
第二步:用戶列表 ThymeLeaf 視圖對(duì)象
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <script type="text/javascript" th:src="@{https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js}"></script>
- <link th:href="@{https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css}" rel="stylesheet"/>
- <link th:href="@{/css/default.css}" rel="stylesheet"/>
- <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
- <meta charset="UTF-8"/>
- <title>用戶列表</title>
- </head>
- <body>
- <div class="contentDiv">
- <h5> 《 Spring Boot 2.x 核心技術(shù)實(shí)戰(zhàn)》第二章快速入門案例</h5>
- <table class="table table-hover table-condensed">
- <legend>
- <strong>用戶列表</strong>
- </legend>
- <thead>
- <tr>
- <th>用戶編號(hào)</th>
- <th>名稱</th>
- <th>年齡</th>
- <th>出生時(shí)間</th>
- <th>管理</th>
- </tr>
- </thead>
- <tbody>
- <tr th:each="user : ${userList}">
- <th scope="row" th:text="${user.id}"></th>
- <td><a th:href="@{/users/update/{userId}(userId=${user.id})}" th:text="${user.name}"></a></td>
- <td th:text="${user.age}"></td>
- <td th:text="${user.birthday}"></td>
- <td><a class="btn btn-danger" th:href="@{/users/delete/{userId}(userId=${user.id})}">刪除</a></td>
- </tr>
- </tbody>
- </table>
- <div><a class="btn btn-primary" href="/users/create" role="button">創(chuàng)建用戶</a></div>
- </div>
- </body>
- </html>
一個(gè) table 展示用戶列表,引入了 jquery.min.js 和 bootstrap.min.css ,更好的展示頁(yè)面效果。具體 ThymeLeaf 語(yǔ)法下面會(huì)講到。
代碼共享在:https://github.com/JeffLi1993/spring-boot-core-book-demo
2.3.1 控制器
什么是控制器?控制器就是控制請(qǐng)求接收和負(fù)責(zé)響應(yīng)到視圖的角色。
@Controller 注解標(biāo)識(shí)一個(gè)類作為控制器。DispatcherServlet 會(huì)掃描所有控制器類,并檢測(cè)
@RequestMapping 注解配置的方法。Web 自動(dòng)化配置已經(jīng)處理完這一步驟。
@RequestMapping 注解標(biāo)識(shí)請(qǐng)求 URL 信息,可以映射到整個(gè)類或某個(gè)特定的方法上。該注解可以表明請(qǐng)求需要的。
使用 value 指定特定的 URL ,比如 @RequestMapping(value = "/users”) 和 @RequestMapping(value = "/users/create”) 等
使用 method 指定 HTTP 請(qǐng)求方法,比如 RequestMethod.GET 等
還有使用其他特定的參數(shù)條件,可以設(shè)置 consumes 指定請(qǐng)求時(shí)的請(qǐng)求頭需要包含的 Content-Type 值、設(shè)置 produces 可確保響應(yīng)的內(nèi)容類型
MVC on REST ful 場(chǎng)景
在 HTTP over JSON (自然 JSON、XML或其他自定義的媒體類型內(nèi)容等均可)場(chǎng)景,配合上前后端分離的開(kāi)發(fā)模式,我們經(jīng)常會(huì)用 @ResponseBody 或 @RestController 兩種方式實(shí)現(xiàn) RESTful HTTP API 。
老方式:
@ResponseBody 注解標(biāo)識(shí)該方法的返回值。這樣被標(biāo)注的方法返回值,會(huì)直接寫入 HTTP 響應(yīng)體(而不會(huì)被視圖解析器認(rèn)為是一個(gè)視圖對(duì)象)。
新方式:
@RestController 注解,和 @Controller 用法一致,整合了 @Controller 和 @ResponseBody 功能。這樣不需要每個(gè) @RequestMapping 方法上都加上 @ResponseBody 注解,這樣代碼更簡(jiǎn)明。
使代碼更簡(jiǎn)明,還有常用便捷注解 @GetMapping、@PostMapping 和 @PutMapping 等
HTTP 協(xié)議相關(guān)知識(shí)回顧,可以看看我以前的博文《圖解 HTTP 協(xié)議》http://www.bysocket.com/?p=282
2.3.2 數(shù)據(jù)綁定
數(shù)據(jù)綁定,簡(jiǎn)單的說(shuō)就是 Spring MVC 從請(qǐng)求中獲取請(qǐng)求入?yún)?,賦予給處理方法相應(yīng)的入?yún)?。主要流程如下?/p>
1. DataBinder 接受帶有請(qǐng)求入?yún)⒌?ServletRequest 對(duì)象
2. 調(diào)用 ConversionService 組件,進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換、數(shù)據(jù)格式化等工作
3. 然后調(diào)用 Validator 組件,進(jìn)行數(shù)據(jù)校驗(yàn)等工作
4. 綁定結(jié)果到 BindingResult 對(duì)象
5. ***賦予給處理方法相應(yīng)的入?yún)?/p>
@ModelAttribute 注解添加一個(gè)或多個(gè)屬性(類對(duì)象)到 model 上。例如
@RequestMapping(value = "/create", method = RequestMethod.POST)
public String postUser(@ModelAttribute User user)
@PathVariable 注解通過(guò)變量名匹配到 URI 模板中相對(duì)應(yīng)的變量。例如
@RequestMapping(value = "/update/{id}", method = RequestMethod.GET)
public String getUser(@PathVariable("id") Long id, ModelMap map)
@RequestParam 注解將請(qǐng)求參數(shù)綁定到方法參數(shù)。
@RequestHeader 注解將請(qǐng)求頭屬性綁定到方法參數(shù)。
2.3.3 視圖和視圖解析
視圖的職責(zé)就是渲染模型數(shù)據(jù),將模型里面的數(shù)據(jù)展示給用戶。
請(qǐng)求到經(jīng)過(guò)處理方法處理后,最終返回的是 ModeAndView ??梢詮?Spring MVC 框架模型 看出,最終經(jīng)過(guò) ViewResolver 視頻解析器得到視圖對(duì)象 View??赡苁俏覀兂R?jiàn)的 JSP ,也可能是基于 ThymLeaf 、FreeMarker 或 Velocity 模板引擎視圖,當(dāng)然還有可能是 JSON 、XML 或者 PDF 等各種形式。
業(yè)界流行的模板引擎有如下的 Starters 支持:
- spring-boot-starter-thymeleaf Thymeleaf 模板視圖依賴,官方推薦
- spring-boot-starter-freemarker Freemarker 模板視圖依賴
- spring-boot-starter-groovy-templates Groovy 模板視圖依賴
- spring-boot-starter-mustache Mustache 模板視圖依賴
具體,spring-boot-starter-thymeleaf 使用案例在 GitHub :https://github.com/JeffLi1993/spring-boot-core-book-demo 的 chapter-2-spring-boot-quick-start 工程。
小結(jié)
本文主要介紹了 Spring Boot 在 Web 開(kāi)發(fā)中涉及到的 HTTP 協(xié)議,還有一些 Spring MVC 相關(guān)的知識(shí)。
推薦:
開(kāi)源項(xiàng)目 springboot-learning-example https://github.com/JeffLi1993/springboot-learning-example
開(kāi)源項(xiàng)目 spring-boot-core-book-demo https://github.com/JeffLi1993/spring-boot-core-book-demo
【本文為51CTO專欄作者“李強(qiáng)強(qiáng)”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)51CTO聯(lián)系作者獲取授權(quán)】