本样板项目基于 Spring 官方的 Spring Initializr 生成的 Spring Boot 项目, 并添加一些实用的常见配置,便于在新项目启动时“简单修改即可复用”。
同时,本项目也将不断跟进上游最新版本,以便下游项目一站式更新。
本项目以容器或云引擎(例: 阿里云 SAE )为部署目标,简化传统的复杂配置,减少更新维护成本。
文件目录结构:
spring-boot-boilerplate-java │ .editorconfig │ .gitattributes │ .gitignore │ docker-compose.yml │ Dockerfile │ LICENSE │ mvnw │ mvnw.cmd │ pom.xml │ README.adoc │ ├─.mvn │ └─wrapper │ maven-wrapper.jar │ maven-wrapper.properties │ MavenWrapperDownloader.java │ ├─docs │ │ Upgrade-Checklist.adoc │ │ │ ├─logback │ │ logback-spring.xml.example │ │ logback-spring.xml.file.example │ │ logback-spring.xml.jdbc.example │ │ logback-spring.xml.sls.example │ │ README.logback.adoc │ │ │ └─maven │ settings.xml │ settings.xml.more-repos.example │ └─src ├─main │ ├─java │ │ └─com │ │ └─example │ │ └─demo │ │ DemoApplication.java │ │ │ └─resources │ │ application-dev.yml │ │ application-prod.yml │ │ application.yml │ │ │ ├─static │ │ .gitkeep │ │ │ └─templates │ .gitkeep │ └─test └─java └─com └─example └─demo DemoApplicationTests.java
-
构建工具:Maven
-
Java 版本:17
与 Spring Initializr 生成的 Spring Boot 项目相比,有如下变动:
-
git 行为配置
-
一个通用的
.gitignore
文件(规定 git 自动忽略哪些文件) -
一个通用的
.gitattributes
文件(规定 git 对文本格式的处理) -
为空目录添加
.gitkeep
文件(0字节,仅占位,避免空目录被忽略)
-
-
编辑器行为配置
-
以
.editorconfig
文件来规范字符编码、行尾、文件末尾、缩进格式等
-
-
Maven Wrapper 使用【阿里云】中国大陆的下载地址,改善下载速度
-
Maven 仓库源并未配置到国内,请参照 配置 Maven 使用镜像源 进行配置
-
-
包含一个基本的
README.adoc
自述文件,以便参考 AsciiDoc 语法-
AsciiDoc 兼容 Markdown 语法,可在
adoc
中直接写 Markdown
-
-
配置文件使用 YAML 格式(
application.yml
取代application.properties
) -
两个项目配置集
-
两个 Maven Profile:
dev
,prod
-
两个 Spring Profile:
dev
,prod
-
启用 Maven Profile
prod
会自动启用对应的 Spring Profileprod
。而dev
亦然
-
-
Docker 描述文件(
Dockerfile
、docker-compose.yml
)-
参照官方最佳实践,使用多段构建
-
-
docs
目录下附带若干帮助文件-
版本升级清单
-
Logback 日志配置样例
-
Maven 镜像源配置样例
-
-
如果你使用 Intellij IDEA / Spring Tool Suite,直接运行项目即可。
-
如果你不想使用 IDE,可以用命令行的方式运行 Spring Boot 项目,你需要先在本地安装:
-
Git
-
JDK 17 或更高版本
-
执行命令:
git clone https://github.com/yanwenkun/spring-boot-boilerplate-java.git
cd spring-boot-boilerplate-java
./mvnw clean spring-boot:run
按 Ctrl + C
可终止运行。
-
全局搜索
DemoApplication
,并替换为你的程序名称,比如SampleApplication
(建议保留Application
后缀) -
全局搜索
com.example.demo
,并替换为你的软件包名称,比如fun.yanwenkun.sample
-
全局搜索
com.example
,并替换为你的组织名称,比如fun.yanwenkun
-
修改
pom.xml
中的软件制品信息(GAV),并管理你的依赖项 -
修改代码文件对应的路径、文件名(可通过 IDE 的重构功能完成)
-
修改
docker-compose.yml
中的容器与镜像名称
启用配置集 | 运行环境 | 数据源 | 日志级别(业务) | 日志级别(框架) |
---|---|---|---|---|
|
开发环境 Development |
运行时 H2 内存数据库 |
TRACE |
INFO |
|
线上测试环境 Testing |
测试数据库 |
DEBUG |
INFO |
预发环境 Staging |
生产数据库 |
INFO |
WARN |
|
生产环境 Production |
生产数据库 |
WARN |
ERROR |
在实际生产中,该表会更为复杂,但原则不变:使问题尽早暴露、尽早解决。
从脱离本地开发环境开始,所有代码与依赖项均应与生产环境一致,仅配置不同。
-
Spring Profile 在 Java/Kotlin 代码中的用法:
-
使用Spring注解:
@Profile("dev")
-
未标
@Profile
注解的代码段,均与配置集无关
-
-
Maven Profile 不关心 Java 代码中的注解,只关心编译资源(依赖项),
pom.xml
中对此有举例
-
容器环境下,日志输出到 STDOUT(标准输出、命令行输出)即可,由容器管理日志的收集
-
程序只需要配置日志输出等级,修改
application-{$profile}.yml
即可 -
如需详细配置 Logback,请参考本项目中的 Spring Logback 日志配置参考
建议:
-
编写代码时不要用
System.out.println()
,而是使用 Slf4j 分等级记录日志-
可用等级(从低到高):
TRACE
DEBUG
INFO
WARN
ERROR
-
Lombok 可以使用 @Slf4j 注解减少代码,但本项目没有引入该依赖
-
-
在以往几乎完全免费的 Oracle JDK ,从2019年开始,只对开发、个人使用免费,用于生产环境需要付费
-
在 2021 年 9 月发布的 Oracle JDK 17,又可以免费用于生产环境了,但只提供三年支持。三年之后要么升级大版本,要么付费买支持,要么停留在最后的免费版本(不安全)
-
而完全免费的 Oracle OpenJDK 只更新最新 GA 大版本,每当新的大版本 GA,老版本即停止更新
-
Oracle 这么做是为了鼓励开发者跟进新版本,同时也扩大老版本的维护收费
-
-
个人建议
-
对于企业开发,“追新”是为了保持先进、与主流同步,“追最新”则容易踩坑、增加成本。正所谓“领先一步是先驱,领先两步是先烈” :-)
-
Java 的下一个长期支持版本(LTS)是 21,预计 2023 年 9 月推出,在其广泛可用(GA)之前,建议维持在 Java 17
-
考虑以下几点:
-
开源
-
有健壮支持
-
完全免费
推荐如下:
-
-
即原先的 AdoptOpenJDK + HotSpot
-
来自 Java 社区重要成员支持的 OpenJDK
-
涵盖大版本较广(8、11、16、17、18 …)
-
老版本(< 16)提供 JRE
-
-
-
即原先的 AdoptOpenJDK + OpenJ9
-
OpenJ9
是来自 IBM 的开源 JVM,为云环境、容器化优化,内存占用小,提供快速启动选项 -
除了 JDK 之外,每个版本还提供 JRE
-
-
-
阿里巴巴开源的 OpenJDK
-
为 LTS 版本提供长期支持
-
随阿里云的工具链分发
-
-
-
亚马逊开源的 OpenJDK
-
为 LTS 版本提供长期支持
-
如果你感到选择困难,请使用 Eclipse Temurin ,它的兼容性最佳。
-
Profile 直译即“档案”,此处理解为配置、配置集
-
配置集包含:配置项 + 专有依赖 + 专有代码
-
对于代码本身,为避免过度复杂,仅使用 2 个配置集:
-
开发阶段专有代码:
@Profile("dev")
-
生产阶段专有代码:
@Profile("prod")
-
-
在本项目中有两种 Profile:
-
Spring Profile
-
Maven Profile
-
-
两者的实际作用域不同
-
Spring Profile 关心代码与配置项
-
Maven Profile 关心编译与依赖项
-
-
为了便于统一管理,本项目中 Spring Profile 和 Maven Profile 共用同一套名称,并通过配置上的绑定,对两者进行了关联
-
比如,Maven 启用了
prod
,Spring 也会启用prod
-
但反过来不会
-
-
如果配置不当,这两种 Profile 可能会冲突
-
同一时间只能有一个 Spring Profile 激活
-
同一时间可以有多个 Maven Profile 激活(在本项目中不推荐这么做)
-
-
dev
与prod
两个命名是 Java 世界中的常见习惯,简洁明了,本项目尊重该习惯 -
Profile 命名并无绝对标准,比如 Spring 官方文档 中就使用了
dev
、staging
、production
作为例子 -
为了避免开发者误解“Profile”与“运行环境”之间的关系,本项目仅使用
dev
与prod
这两个 Profile-
dev
仅在开发环境有效,脱离开发环境即开始使用prod
,使潜在问题尽早暴露
-
实际上,在高度 CI/CD 化之后,开发者不需要过多关心运行环境,而是应该精简配置、写好配置样板,供运维在不同阶段灵活部署。
某种意义上,这两个 Profile 的含义可以理解为 DEBUG
与 RELEASE
,或者 local
与 online
。
-
开发(本地编码)、验证(各类测试)、生产(发布上线):
-
既是软件生命周期中的“阶段”
-
也是运维与服务治理中的“环境”
-
-
分得过于详细,有过度设计之虞,概念越多越容易出错
-
作为“偷懒”的做法,将阶段和环境合为一谈,主要目的在于减少心智负担
-
但扩大开发规模的时候,还是要注意概念上的区分
-
见: 版本升级清单 。
从工程管理的角度出发,Java 项目保持其代码风格的延续是很重要的。而 Lombok 的侵入性,对老项目而言是需要权衡的,请根据团队的意见做出选择。
对于没有历史负担的新项目,可以考虑 Kotlin 。
在不配置 Maven 插件(即不改动 pom.xml
)的前提下,最简单的方法是使用命令行调用 Google Jib:
-
用法1:构建镜像
./mvnw com.google.cloud.tools:jib-maven-plugin:dockerBuild -Dimage="example/demo:dev"
-
用法2:构建镜像并推送至仓库(Docker Registry)
./mvnw com.google.cloud.tools:jib-maven-plugin:build -Dimage="example/demo:dev"
注意修改镜像名称与标签 example/demo:dev
。
推送至仓库前需要先登录(docker login
)。
在中国大陆访问 Maven 官方源一般会很慢,建议使用镜像源。
-
不推荐直接在
pom.xml
中配置仓库来源-
因为初次构建时还是要从官方源下载包,依然很慢
-
不利于 CI 的管理
-
如何配置本地 Maven 使用镜像源:
将【 settings.xml 】复制到【 用户主目录/.m2/ 】下。 或执行命令:
mkdir ~/.m2/
cp docs/maven/settings.xml ~/.m2/
如需 Maven Central 以外的仓库源,请参考【 settings.xml.more-repos.example 】。
本项目使用与 Spring Boot 一致的 Apache License 2.0 许可。