重拾后端之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}") }
}复制代码