
重拾后端之Spring Boot(一):REST API的搭建可以這樣簡單
重拾后端之Spring Boot(二):MongoDb的無縫集成
重拾后端之Spring Boot(三):找回熟悉的Controller,Service
重拾后端之Spring Boot(四):使用 JWT 和 Spring Security 保護 REST API
重拾后端之Spring Boot(五):跨域、自定義查詢及分頁
重拾后端之Spring Boot(六):熱加載、容器和多項目
話說我當年接觸Spring的時候著實興奮了好一陣,IoC的概念當初第一次聽說,感覺有種開天眼的感覺。記得當時的web框架和如今的前端框架的局面差不多啊,都是群雄紛爭。但一晃好多年沒寫過后端,代碼這東西最怕手生,所以當作重新學(xué)習(xí)了,順便寫個學(xué)習(xí)筆記。
Spring Boot是什么?
還恍惚記得當初寫Spring的時候要配置好多xml(在當時還是相對先進的模式),雖然實現(xiàn)了松耦合,但這些xml卻又成為了項目甩不掉的負擔 -- 隨著項目越做越大,這些xml的可讀性和可維護性極差。后來受.Net平臺中Annotation的啟發(fā),Java世界中也引入了元數(shù)據(jù)的修飾符,Spring也可以使用這種方式進行配置。到了近些年,隨著Ruby on Rails的興起而流行開的 Convention over configuration 理念開始深入人心。那什么是 Convention over configuration 呢?簡單來說就是犧牲一部分的自由度來減少配置的復(fù)雜度,打個比方就是如果你如果遵從我定義的一系列規(guī)則(打個比方,文件目錄結(jié)構(gòu)必須是blablabla的樣子,文件命名必須是nahnahnah 的樣子),那么你要配置的東西就非常簡單甚至可以零配置。既然已經(jīng)做到這個地步了,各種腳手架項目就紛紛涌現(xiàn)了,目的只有一個:讓你更專注在代碼的編寫,而不是浪費在各種配置上。這兩年前端也有類似趨勢,各種前端框架的官方CLI紛紛登場:create-react-app,angular-cli,vue-cli等等。
那么Spring Boot就是Spring框架的腳手架了,它可以幫你快速搭建、發(fā)布一個Spring應(yīng)用。官網(wǎng)列出了Spring Boot的幾個主要目標
- 提供一種快速和廣泛適用的Spring開發(fā)體驗
- 開箱即用卻又可以適應(yīng)各種變化
- 提供一系列開發(fā)中常用的“非功能性”的特性(比如嵌入式服務(wù)器、安全、度量、自檢及外部配置等)
- 不生成任何代碼,不需要xml配置
安裝Spring Boot
官方推薦的方式是通過sdkman( http://sdkman.io/install.html )來進行安裝,當然這是對 *nix 而言。題外話,如果你使用的是Windows 10,真心希望大家安裝Windows 10的Linux子系統(tǒng),微軟官方出品、原生支持,比虛擬機不知道快到那里去了 具體安裝過程可以參考 https://linux.cn/article-7209-1.html 。安裝 sdkman 的步驟非常簡單,就兩步:
- 打開一個terminal,輸入
curl -s "https://get.sdkman.io" | bash - 安裝結(jié)束后,重啟terminal,輸入
source "$HOME/.sdkman/bin/sdkman-init.sh"
可以在terminal中驗證一下是否安裝成功 sdk version,如果你看到了版本號就是安裝好了。
接下來,就可以安裝Spring Boot了,還是打開terminal輸入 sdk install springboot就ok了。
當然其實Mac的童鞋可以省略掉之前的sdkman安裝直接使用 brew 安裝,也是兩步:
- 在terminal中輸入
brew tap pivotal/tap - 然后
brew install springboot
驗證的話可以輸入 spring --version 看看是否正常輸出了版本號。
創(chuàng)建一個工程
有很多種方法可以創(chuàng)建一個Spring Boot項目,其中最簡單的一種是通過一個叫Spring Initializr的在線工具 http://start.spring.io/ 進行工程的生成。如下圖所示,只需填寫一些參數(shù)就可以生成一個工程包了。

如果你使用Intellij IDEA進行開發(fā),里面也集成了這個工具,大家可以自行嘗試。

但下面我們要做的不是通過這種方式,而是手動的通過命令行方式創(chuàng)建。創(chuàng)建的是gradle工程,而不是maven的,原因呢是因為個人現(xiàn)在對于xml類型的配置文件比較無感;-),官方推薦使用gradle 2.14.1版本,請自行安裝gradle。下面來建立一個gradle工程,其實步驟也不算太難:
- 新建一個工程目錄
mkdir todo - 在此目錄下使用gradle進行初始化
gradle init(就和在node中使用npm init的效果類似)
這個命令幫我們建立一個一個使用gradle進行管理的模版工程:
-
build.gradle:有過Android開發(fā)經(jīng)驗的童鞋可能覺得很親切的,這個就是我們用于管理和配置工程的核心文件了。 -
gradlew:用于*nix環(huán)境下的gradle wrapper文件。 -
gradlew.bat:用于Windows環(huán)境下的gradle wrapper文件 -
setting.gradle:用于管理多項目的gradle工程時使用,單項目時可以不做理會。 - gradle目錄:wrapper的jar和屬性設(shè)置文件所在的文件夾。
簡單說兩句什么是 gradle wrapper。你是否有過這樣的經(jīng)歷?在安裝/編譯一個工程時需要一些先決條件,需要安裝一些軟件或設(shè)置一些參數(shù)。如果這一切比較順利還好,但很多時候我們會發(fā)現(xiàn)這樣那樣的問題,比如版本不對,參數(shù)沒設(shè)置等等。gradle wrapper 就是這樣一個讓你不會浪費時間在配置問題上的方案。它會對應(yīng)一個開發(fā)中使用的gradle版本,以確保任何人任何時候得到的結(jié)果是一致的。
-
./gradlew <task>: 在*nix平臺上運行,例如Linux或Mac OS X -
gradlew <task>在Windows平臺運行(是通過gradlew.bat來執(zhí)行的)
更多關(guān)于wrapper的知識可以去 https://docs.gradle.org/current/userguide/gradle_wrapper.html 查看。
那么下面我們打開默認生成的 build.gradle 文件,將其改造成下面的樣子:
/*
* 這個build文件是由Gradle的 `init` 任務(wù)生成的。
*
* 更多關(guān)于在Gradle中構(gòu)建Java項目的信息可以查看Gradle用戶文檔中的
* Java項目快速啟動章節(jié)
* https://docs.gradle.org/3.3/userguide/tutorial_java_projects.html
*/
// 在這個段落中你可以聲明你的build腳本需要的依賴和解析下載該依賴所使用的倉儲位置
buildscript {
ext {
springBootVersion = '1.4.3.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
/*
* 在這個段落中你可以聲明使用哪些插件
* apply plugin: 'java' 代表這是一個Java項目,需要使用java插件
* 如果想生成一個 `Intellij IDEA` 的工程,類似的如果要生成
* eclipse工程,就寫 apply plugin: 'eclipse'
* 同樣的我們要學(xué)的是Spring Boot,所以應(yīng)用Spring Boot插件
*/
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'
// 在這個段落中你可以聲明編譯后的Jar文件信息
jar {
baseName = 'todo'
version = '0.0.1-SNAPSHOT'
}
// 在這個段落中你可以聲明在哪里可以找到你的項目依賴
repositories {
// 使用 'jcenter' 作為中心倉儲查詢解析你的項目依賴。
// 你可以聲明任何 Maven/Ivy/file 類型的依賴類庫倉儲位置
mavenCentral()
}
// 在這個段落中你可以聲明源文件和目標編譯后的Java版本兼容性
sourceCompatibility = 1.8
targetCompatibility = 1.8
// 在這個段落你可以聲明你的項目的開發(fā)和測試所需的依賴類庫
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
首先腳本依賴中的 spring-boot-gradle-plugin 有什么作用呢?它提供了以下幾個功能:
- 簡化執(zhí)行和發(fā)布:它可以把所有classpath的類庫構(gòu)建成一個單獨的可執(zhí)行jar文件,這樣可以簡化你的執(zhí)行和發(fā)布等操作。
- 自動搜索入口文件:它會掃描
public static void main()函數(shù)并且標記這個函數(shù)的宿主類為可執(zhí)行入口。 - 簡化依賴:一個典型的Spring應(yīng)用還是需要很多依賴類庫的,想要配置正確這些依賴挺麻煩的,所以這個插件提供了內(nèi)建的依賴解析器會自動匹配和當前Spring Boot版本匹配的依賴庫版本。
在最后一個段落中,我們看到我們的項目依賴兩個類庫,一個是 spring-boot-starter-web ,另一個是 spring-boot-starter-test。Spring Boot提供了一系列依賴類庫的“模版”,這些“模版”封裝了很多依賴類庫,可以讓我們非常方便的引用自己想實現(xiàn)的功能所需要的類庫。如果我們?nèi)タ纯催@個 spring-boot-starter-web 中究竟引用了什么,我們可以看看它的artifact文件(到 http://search.maven.org/ 可以查看):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starters</artifactId>
<version>1.4.3.RELEASE</version>
</parent>
<artifactId>spring-boot-starter-web</artifactId>
<name>Spring Boot Web Starter</name>
<description>Starter for building web, including RESTful, applications using Spring
MVC. Uses Tomcat as the default embedded container</description>
<url>http://projects.spring.io/spring-boot/</url>
<organization>
<name>Pivotal Software, Inc.</name>
<url>http://www.spring.io</url>
</organization>
<properties>
<main.basedir>${basedir}/../..</main.basedir>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies>
</project>
IDE支持
一般做Java開發(fā),大部分團隊還是喜歡用一個IDE,雖然我還是更偏愛文本編輯器類型的(比如sublime,vscode,atom等)。但是如果非挑一個重型IDE的話,我更喜歡Intellij IDEA。
使用IDEA的import project功能選中 build.gradle,將工程導(dǎo)入。由于是個gradle工程,請把 View->Tools Window->Gradle 的視圖窗口調(diào)出來。

點擊左上角的刷新按鈕可以將所有依賴下載類庫下來。注意IDEA有時提示是否要配置wrapper使用帶源碼的gradle包。

如果遇到不知道什么原因?qū)е乱恢彼⑿峦瓿刹涣说那闆r,請在項目屬性中選擇 Use local gradle distribution

第一個Web API
領(lǐng)域?qū)ο?/h3>
那么我們的源代碼目錄在哪里呢?我們得手動建立一個,這個目錄一般情況下是 src/main/java。好的,下面我們要開始第一個RESTful的API搭建了,首先還是在 src/main/java 下新建一個 package。既然是本機的就叫 dev.local 吧。我們還是來嘗試建立一個 Todo 的Web API,在 dev.local 下建立一個子 package: todo,然后創(chuàng)建一個Todo的領(lǐng)域?qū)ο螅?/p>
package dev.local.todo;
/**
* Todo是一個領(lǐng)域?qū)ο螅╠omain object)
* Created by wangpeng on 2017/1/24.
*/
public class Todo {
private String id;
private String desc;
private boolean completed;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public boolean isCompleted() {
return completed;
}
public void setCompleted(boolean completed) {
this.completed = completed;
}
}
這個對象很簡單,只是描述了todo的幾個屬性: id 、 desc 和 completed 。我們的API返回或接受的參數(shù)就是以這個對象為模型的類或集合。
構(gòu)造Controller
我們經(jīng)??吹降腞ESTful API是這樣的:http://local.dev/todos、http://local.dev/todos/1 。Controller就是要暴露這樣的API給外部使用?,F(xiàn)在我們同樣的在 todo 下建立一個叫 TodoController 的java文件
package dev.local.todo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
/**
* 使用@RestController來標記這個類是個Controller
*/
@RestController
public class TodoController {
// 使用@RequstMapping指定可以訪問的URL路徑
@RequestMapping("/todos")
public List<Todo> getAllTodos() {
List<Todo> todos = new ArrayList<>();
Todo item1 = new Todo();
item1.setId("1");
item1.setCompleted(false);
item1.setDesc("go swimming");
todos.add(item1);
Todo item2 = new Todo();
item2.setId("1");
item2.setCompleted(true);
item2.setDesc("go for lunch");
todos.add(item2);
return todos;
}
}
上面這個文件也比較簡單,但注意到以下幾個事情:
-
@RestController和@RequestMapping這兩個是元數(shù)據(jù)注釋,原來在.Net中很常見,后來Java也引進過來。一方面它們可以增加代碼的可讀性,另一方面也有效減少了代碼的編寫。具體機理就不講了,簡單來說就是利用Java的反射機制和IoC模式結(jié)合把注釋的特性或?qū)傩宰⑷氲奖蛔⑨尩膶ο笾小?/li> - 我們看到
List<Todo> getAllTodos()方法中簡單的返回了一個List,并未做任何轉(zhuǎn)換成json對象的處理,這個是Spring會自動利用Jackson這個類庫的方法將其轉(zhuǎn)換成了json。
我們到這就基本接近成功了,但是現(xiàn)在缺少一個入口,那么在 dev.local 包下面建立一個 Applicaiton.java 吧。
package dev.local;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* Spring Boot 應(yīng)用的入口文件
* Created by wangpeng on 2017/1/24.
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
同樣的我們只需標注這個類是 @SpringBootApplication 就萬事大吉了。可以使用下面任意一種方法去啟動我們的Web服務(wù):
- 命令行中:
./gradlew bootRun - IDEA中在
Application中右鍵選擇Run 'Application'

啟動后,打開瀏覽器訪問 http://localhost:8080/todos 就可以看到我們的json形式的返回結(jié)果了。

配置Spring Beans工具
由于使用的是Spring框架,Spring工具窗口也是需要的,一般來說如果你安裝了Spring插件的話,IDEA會自動探測到你的項目是基于Spring的。一般在你增加了Applicaiton入口后,會提示是否添加context。

遇到這種情況,請點提示框的右方的下箭頭展開提示。

點擊 Create Default Context 會將目前的所有沒有map的Spring配置文件都放在這個默認配置的上下文中。在Spring的工具窗口中可以看到下圖效果。

本章代碼:https://github.com/wpcfan/spring-boot-tut/tree/chap01
慕課網(wǎng) Angular 視頻課上線: http://coding.imooc.com/class/123.html?mc_marking=1fdb7649e8a8143e8b81e221f9621c4a&mc_channel=banner
重拾后端之Spring Boot(一):REST API的搭建可以這樣簡單
重拾后端之Spring Boot(二):MongoDb的無縫集成
重拾后端之Spring Boot(三):找回熟悉的Controller,Service
重拾后端之Spring Boot(四):使用 JWT 和 Spring Security 保護 REST API
重拾后端之Spring Boot(五):跨域、自定義查詢及分頁
有問題的童鞋可以加入我的小密圈討論: http://t.xiaomiquan.com/jayRnaQ (該鏈接7天內(nèi)(5月14日前)有效)
另外,我的 《Angular 從零到一》出版了,下面是書籍的內(nèi)容簡介:
本書系統(tǒng)介紹Angular的基礎(chǔ)知識與開發(fā)技巧,可幫助前端開發(fā)者快速入門。共有9章,第1章介紹Angular的基本概念,第2~7章從零開始搭建一個待辦事項應(yīng)用,然后逐步增加功能,如增加登錄驗證、將應(yīng)用模塊化、多用戶版本的實現(xiàn)、使用第三方樣式庫、動態(tài)效果制作等。第8章介紹響應(yīng)式編程的概念和Rx在Angular中的應(yīng)用。第9章介紹在React中非常流行的Redux狀態(tài)管理機制,這種機制的引入可以讓代碼和邏輯隔離得更好,在團隊工作中強烈建議采用這種方案。本書不僅講解Angular的基本概念和最佳實踐,而且分享了作者解決問題的過程和邏輯,講解細膩,風趣幽默,適合有面向?qū)ο缶幊袒A(chǔ)的讀者閱讀。
歡迎大家圍觀、訂購、提出寶貴意見。
京東鏈接:https://item.m.jd.com/product/12059091.html?from=singlemessage&isappinstalled=0
