重拾后端之Spring Boot(六) -- 热加载、容器和多项目

重拾后端之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 的热加载 (Live Load)

Spring Boot 内建提供了支持热加载的功能,这个机制是经过 spring-dev-tools 来实现的。要实现这样的功能,须要如下几个步骤spring

第一步:在项目依赖中添加 spring-dev-tools:在 build.gradle 中添加mongodb

dependencies {
     compile("org.springframework.boot:spring-boot-devtools")
 }复制代码

第二步:因为咱们会链接到应用的一个自动装载器上,因此须要提供一个共享密钥:在 application.ymlapplication.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 automaticallyjson

IDEA 中勾选 Build project automatically
IDEA 中勾选 Build project automatically

在 IDEA 的 registry 中勾选 compiler.automake.allow.when.app.running (macOS 下使用 option + command + shift + / ,Windows 下使用 Ctrl + Alt + Shift + / 调出 registry 菜单)后端

用快捷键调出 registry 菜单
用快捷键调出 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:8090Working Directory 填写 $MODULE_DIR$,而 Use classpath of module 选择当前项目便可。

建立一个 Spring Boot 的 Run/Debug 模板配置
建立一个 Spring Boot 的 Run/Debug 模板配置

远程调试

IDEA 提供了很是良好的远程调试支持,添加远程调试的话,能够去 Run/Debug Configurations 中新建一个 Remote 类型的配置,其中默认端口为 8000,Transport 选择 SocketDebug Mode 选择 Attach 便可。这种远程调试能够支持在 Docker 容器中进行调试,方便团队的环境容器化。

添加远程调试
添加远程调试

容器支持

使用容器(Docker)来发布 Spring Boot 项目很是简单。若是你采用 Gradle 构建的话,能够不用写 Dockerfile ,直接在 build.gradle 中创建一个 buildDocker 的任务便可。固然要支持这样的任务的话,咱们须要首先在 buildscriptdependencies 中引入 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 就成为了根项目,而 commonapireport 就是其之下的子项目。接下来,咱们看一下根项目的 build.gradle,对于多项目构建来讲,根项目的 build.gradle 中应该尽量的配置各子项目中共同的配置,从而让子项目只配置本身不一样的东西。

// 一个典型的根项目的构建文件结构
buildscript {
    /*
     * 构建脚本段落能够配置整个项目须要的插件,构建过程当中的依赖以及依赖类库的版本号等
     */
}

allprojects {
    /*
     * 在这个段落中你能够声明对于全部项目(含根项目)都适用的配置,好比依赖性的仓储等
     */
}

subprojects {
    /*
     * 在这个段落中你能够声明适用于各子项目的配置(不包括根项目哦)
     */
    version = "0.0.1"
}

/*
 * 对于子项目的特殊配置
 */
project(':common') {

}

project(':api') {

}

project(':report') {

}复制代码

其中,buildscript 段落用于配置 gradle 脚本生成时须要的东西,好比配置整个项目须要的插件,构建过程当中的依赖以及在其余部分须要引用的依赖类库的版本号等,就像下面这样,咱们在 ext 中定义了一些变量来集中配置了全部依赖的版本号,不管是根项目仍是子项目均可以使用这些变量来指定版本号。这样作的好处是当依赖的版本更新时,咱们无需四处更改散落在各处的版本号。此外在这个段落中咱们还提供了项目所需的第三方 Gradle 插件所需的依赖:spring-boot-gradle-plugingradle-dockerdependency-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 中能够声明对于全部项目(含根项目)都适用的配置,好比依赖性的仓储等。而 subprojectsallprojects 的区别在于 subprojecrts 只应用到子项目,而非根项目。因此大部分通用型配置能够经过 subprojectsallprojects 来完成。下面列出的样例配置中,咱们为全部的项目包括根项目配置了依赖仓储以及软件的 group,同时为每一个子项目配置了 javaidea 两个插件、版本号和通用的测试依赖。

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 中如何构建类库工程

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}") }
}复制代码
相关文章
相关标签/搜索