重拾後端之Spring Boot(一):REST API的搭建能夠這樣簡單
重拾後端之Spring Boot(二):MongoDb的無縫集成
重拾後端之Spring Boot(三):找回熟悉的Controller,Service
重拾後端之Spring Boot(四):使用 JWT 和 Spring Security 保護 REST API
重拾後端之 Spring Boot(五) -- 跨域、自定義查詢及分頁
重拾後端之Spring Boot(六) -- 熱加載、容器和多項目java
這一章主要總結一下 Spring Boot 相關的環境配置和工具支持。web
Spring Boot 內建提供了支持熱加載的功能,這個機制是經過 spring-dev-tools
來實現的。要實現這樣的功能,須要如下幾個步驟spring
第一步:在項目依賴中添加 spring-dev-tools
:在 build.gradle
中添加mongodb
dependencies {
compile("org.springframework.boot:spring-boot-devtools")
}複製代碼
第二步:因爲咱們會鏈接到應用的一個自動裝載器上,因此須要提供一個共享密鑰:在 application.yml
或 application.properties
中添加docker
若是是 application.yml
的話,請按此填寫:數據庫
spring:
devtools:
remote:
secret: thisismysecret複製代碼
若是是 application.properties
的話,請按此填寫:apache
# 若是是 application.properties 請按此填寫
spring.devtools.remote.secret=thisismysecret複製代碼
第三步:在 Intellij IDEA 當中的 Preference
-> Build, Execution, Deployment
-> Compiler
中勾選 Build project automatically
json
在 IDEA 的 registry 中勾選 compiler.automake.allow.when.app.running
(macOS 下使用 option
+ command
+ shift
+ /
,Windows 下使用 Ctrl
+ Alt
+ Shift
+ /
調出 registry 菜單)後端
而後尋找到 compiler.automake.allow.when.app.running
,進行勾選api
最後重啓 IDE,在 Run/Debug Configurations
中新建一個 Spring Boot
模板的配置。其中 Main Class
填入 org.springframework.boot.devtools.RemoteSpringApplication
(注意哦,點右邊的省略號按鈕勾選 include non-project classes
的選擇纔有效)。而後在 Program arguments
中填入服務地址,好比你的服務端口是 8090
就填 http://localhost:8090
; Working Directory
填寫 $MODULE_DIR$
,而 Use classpath of module
選擇當前項目便可。
IDEA 提供了很是良好的遠程調試支持,添加遠程調試的話,能夠去 Run/Debug Configurations
中新建一個 Remote
類型的配置,其中默認端口爲 8000
,Transport 選擇 Socket
,Debug Mode
選擇 Attach
便可。這種遠程調試能夠支持在 Docker 容器中進行調試,方便團隊的環境容器化。
使用容器(Docker)來發布 Spring Boot 項目很是簡單。若是你採用 Gradle 構建的話,能夠不用寫 Dockerfile ,直接在 build.gradle
中創建一個 buildDocker
的任務便可。固然要支持這樣的任務的話,咱們須要首先在 buildscript
的 dependencies
中引入 se.transmode.gradle:gradle-docker
的類庫,而後應用 docker
插件(apply plugin: 'docker'
)
buildscript {
// 省略其餘部分
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath('se.transmode.gradle:gradle-docker:1.2')
}
}
apply plugin: 'docker'
// docker 的 group
group = 'wpcfan'
// 創建 docker image
task buildDocker(type: Docker, dependsOn: build) {
baseImage = 'frolvlad/alpine-oraclejdk8:slim' // 基於 jdk 的鏡像拓展
tag = 'wpcfan/taskmgr-backend' // 要推送到 docker hub 的『組名/項目名』
push = true
applicationName = jar.baseName
addFile {
from jar
rename {'app.jar'}
}
entryPoint([
'java',
'-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n',
'-Dspring.data.mongodb.uri=mongodb://mongodb/taskmgr',
'-Djava.security.egd=file:/dev/./urandom',
'-jar',
'/app.jar'
])
exposePort(8090)
}複製代碼
其中 entryPoint
中的幾個參數含義分別是
-Xdebug -Xrunjdwp:server=y,transport=dt_socket,suspend=n
是讓容器能夠支持 IDEA 遠程調試-Dspring.data.mongodb.uri=mongodb://mongodb/taskmgr
是指定 mongodb
的鏈接 URL,由於咱們的 mongodb 也是容器,因此鏈接方式上須要使用『協議/主機名/數據庫』的方式。
兩個容器若是互相須要通訊的話,若是在不一樣主機,指定 IP 是能夠的,但在同一個主機上怎麼破呢?這時候咱們就須要利用 --link
指定要鏈接的容器(該選項後跟的是容器名稱),好比咱們要鏈接 mongodb
容器,就寫成下面的樣子就好了。
docker run -p 80:8090 --name taskmgr-backend wpcfan/taskmgr-backend --link mongodb複製代碼
在大型軟件開發中,一個項目解決全部問題顯然不可取的,由於存在太多的開發團隊共同協做,因此對項目進行拆分,造成多個子項目的形式是廣泛存在的。並且一個子項目只專一本身的邏輯也易於維護和拓展,如今隨着容器和微服務的理念逐漸得到你們的承認,多個子項目分別發佈到容器和造成多個微服務也逐漸成爲趨勢。
咱們的項目使用 Gradle 來處理多項目的構建,包括大項目和子項目的依賴管理以及容器的創建等。對於 Gradle 項目來講,咱們會有一個根項目,這個根項目下會創建若干子項目,具體文件結構以下:
|--spring-boot-tut (根項目)
|----common (共享子項目)
|------src (子項目源碼目錄)
|--------main (子項目開發源碼目錄)
|----------java(子項目開發 Java 類源碼目錄)
|----------resources(子項目資源類源碼目錄)
|------build.gradle (子項目 gradle 構建文件)
|----api (API 子項目)
|------src
|--------main
|----------java
|----------resources
|------build.gradle
|----report (報表子項目)
|------src
|--------main
|----------java
|----------resources
|------build.gradle
|--build.gradle (根項目構建文件)
|--settings.gradle (根項目設置文件)複製代碼
要讓 Gradle 支持多項目的話,首先須要把 settings.gradle
改爲
include 'common'
include 'api'
include 'report'
rootProject.name = 'spring-boot-tut'複製代碼
這樣 spring-boot-tut
就成爲了根項目,而 common
、api
和 report
就是其之下的子項目。接下來,咱們看一下根項目的 build.gradle
,對於多項目構建來講,根項目的 build.gradle
中應該儘量的配置各子項目中共同的配置,從而讓子項目只配置本身不一樣的東西。
// 一個典型的根項目的構建文件結構
buildscript {
/*
* 構建腳本段落能夠配置整個項目須要的插件,構建過程當中的依賴以及依賴類庫的版本號等
*/
}
allprojects {
/*
* 在這個段落中你能夠聲明對於全部項目(含根項目)都適用的配置,好比依賴性的倉儲等
*/
}
subprojects {
/*
* 在這個段落中你能夠聲明適用於各子項目的配置(不包括根項目哦)
*/
version = "0.0.1"
}
/*
* 對於子項目的特殊配置
*/
project(':common') {
}
project(':api') {
}
project(':report') {
}複製代碼
其中,buildscript
段落用於配置 gradle
腳本生成時須要的東西,好比配置整個項目須要的插件,構建過程當中的依賴以及在其餘部分須要引用的依賴類庫的版本號等,就像下面這樣,咱們在 ext
中定義了一些變量來集中配置了全部依賴的版本號,不管是根項目仍是子項目均可以使用這些變量來指定版本號。這樣作的好處是當依賴的版本更新時,咱們無需四處更改散落在各處的版本號。此外在這個段落中咱們還提供了項目所需的第三方 Gradle 插件所需的依賴:spring-boot-gradle-plugin
、gradle-docker
和 dependency-management-plugin
,這樣在後面,各子項目能夠簡單的使用諸如 apply plugin: 'io.spring.dependency-management'
、 apply plugin: 'docker'
等便可。
buildscript {
ext {
springBootVersion = '1.5.4.RELEASE'
springCtxSupportVersion = '4.2.0.RELEASE'
lombokVersion = '1.16.16'
jjwtVersion = '0.7.0'
jasperVersion = '6.4.0'
poiVersion = '3.16'
itextVersion = '2.1.7'
olap4jVersion = '1.2.0'
gradleDockerVersion = '1.2'
gradleDMVersion = '1.0.3.RELEASE'
}
repositories {
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("se.transmode.gradle:gradle-docker:${gradleDockerVersion}")
classpath("io.spring.gradle:dependency-management-plugin:${gradleDMVersion}")
}
}複製代碼
allprojects
中能夠聲明對於全部項目(含根項目)都適用的配置,好比依賴性的倉儲等。而 subprojects
和 allprojects
的區別在於 subprojecrts
只應用到子項目,而非根項目。因此大部分通用型配置能夠經過 subprojects
和 allprojects
來完成。下面列出的樣例配置中,咱們爲全部的項目包括根項目配置了依賴倉儲以及軟件的 group
,同時爲每一個子項目配置了 java
和 idea
兩個插件、版本號和通用的測試依賴。
allprojects {
group = 'spring-tut'
repositories() {
jcenter()
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'idea'
version = "0.0.1"
dependencies {
testCompile("org.springframework.boot:spring-boot-starter-test")
}
}複製代碼
除此以外呢,爲了展現一下 project
的用法, 咱們這個例子裏把每一個子項目的依賴放到根 build.gradle
中的 project(':子項目名')
中列出,這樣作有好處也有缺點,好處是依賴性的管理統一在根 build.gradle
完成,對於依賴的狀況一目瞭然。固然缺點是每一個項目更改依賴時都會形成根 gradle
的更新,這樣的話若是一個項目有很是多的子項目時,會在協做上出現一些問題。因此請根據具體狀況決定把依賴放到根 build.gradle
中的 project(':子項目名')
中仍是放到各子項目的 build.gradle
中。
project(':common') {
dependencies {
compile("org.springframework.boot:spring-boot-starter-data-rest")
compile("org.springframework.boot:spring-boot-starter-data-mongodb")
compile("org.projectlombok:lombok:${lombokVersion}")
}
}
project(':api') {
dependencies {
compile project(':common')
compile("org.springframework.boot:spring-boot-devtools")
compile("org.springframework.boot:spring-boot-starter-security")
compile("io.jsonwebtoken:jjwt:${jjwtVersion}")
compile("org.projectlombok:lombok:${lombokVersion}")
}
}
project(':report') {
dependencies {
compile project(':common')
compile("org.springframework.boot:spring-boot-devtools")
// the following 5 are required by jasperreport rendering
compile files(["lib/simsun.jar"])
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework:spring-context-support:${springCtxSupportVersion}")
compile("net.sf.jasperreports:jasperreports:${jasperVersion}")
compile("com.lowagie:itext:${itextVersion}")
compile("org.apache.poi:poi:${poiVersion}")
compile("org.olap4j:olap4j:${olap4jVersion}")
}
}複製代碼
Spring Boot 的一大優勢就是把應用作成了一個 Fat Jar,這種方式在部署時有極大的優點。但如何在 Spring Boot 的多項目構建中創建一個類庫工程,而不是應用工程呢?固然前提是咱們還能繼續享受 Spring Boot 帶來的配置便利性。
首先,咱們須要在根工程的 build.gradle
中添加一個 Spring Boot 依賴管理的插件:
buildscript {
ext {
springBootVersion = '1.5.4.RELEASE'
gradleDMVersion = '1.0.3.RELEASE'
}
repositories {
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
classpath("io.spring.gradle:dependency-management-plugin:${gradleDMVersion}")
}
}複製代碼
而後在類庫子項目中的 build.gradle
中添加下面這句便可。
dependencyManagement {
imports { mavenBom("org.springframework.boot:spring-boot-dependencies:${springBootVersion}") }
}複製代碼