spring boot介绍Spring Boot目前流行的java web应用开发框架,相比传统的spring开发,spring boot极大简化了配置,并且遵守约定优于配置的原则即使0配置也能正常运行,这在spring中是难以想象的。spring boot应用程序可以独立运行,框架内嵌web容器,使得web应用程序可以像本地程序一样启动和调试,十分的方便,这种设计方式也使得spring boot应用程序非常适合容器化进行大规模部署。生态方面,spring boot提供了非常丰富的组件,目前流行的java web框架基本都有spring boot版本,生态十分庞大,是目前java web开发最好的方案。 spring boot部署问题Springboot应用程序有两种运行方式 两种方式应用场景不一样,各有优缺点 jar包运行通过maven插件spring-boot-maven-plugin ,在进行打包时,会动态生成jar的启动类org.springframework.boot.loader.JarLauncher ,借助该类对springboot应用程序进行启动。 优点- 本地无需搭建web容器,方便开发和调试。
- 因为自带web容器,可以避免由于web容器的差异造成不同环境结果不一致问题。
- 一个jar包就是全部,方便应用扩展。
- 借助容器化,可以进行大规模的部署。
缺点- 应用过于独立,难以统一管理。
- 数据源无法通过界面进行管理。
- 应用体积过大。
- 修改web容器相关配置较为困难,需要借助代码实现。
war包运行以war包方式运行,通过maven插件spring-boot-maven-plugin 进行相关配置后,最终生成一个可运行在tomcat,weblogic等java web容器中的war包。 优点- 可以借助web容器管理界面对应用进行管理。
- 可以管理JNDI数据源。
- web容器配置较为灵活,配置和程序分离。
- 应用体积较小,甚至可以借助web容器的包管理功能(比如weblogic Library)进一步减小应用大小。
缺点- 本地需要搭建web容器,对本地环境要求更高点,学习成本也响应更高。
- 调试较为困难,需要借助web容器。
- 无法兼容所有web容器(比如spring boot2.x无法运行在weblogic 11g上)。
- 部署较为困难(比如和weblogic有较多的类冲突)
在实际的项目中,并没有哪一种方式是最好的,根据客户不同的需求制定不同的部署方案,比如有些客户比较看中管理功能,要求数据源和tomcat相关配置必须由管理员进行管理,那么选择war包方式,有些客户希望借助容器化进行大规模部署,那么jar方式更适合。不管选择哪种方式,在部署时都会遇到下面的问题 - 如果需要打war包,那么不仅是pom文件需要修改,应用程序也要做相应的改动,改动完后,应用程序就无法本地运行,需要打完包后将配置信息修改回来,这样不仅麻烦,还容易出错。
- 不管是war包还是jar包,如何管理不同环境的配置文件,保证不会出错,虽然spring boot有提供
spring.profiles.active 配置设置不同的环境,但一方面需要人为修改配置文件,只要是人为的就有可能出错,另一方面,客户有时出于安全考虑不会提供生产环境配置信息,那么这时候就无法指定prifiles.active 。 - 如何将多个spring boot模块打包在一起。
- jar包需要配合容器化才能发挥出最大的优势,如果没有容器,spring boot jar包就是一个
玩具 ,随处运行的jar包,缺少统一管理,是达不到生产的要求,那么如果从jar包到容器也是一个问题。
早期碰到这些问题,都是人工解决,不仅效率十分低下,部署一次都需要十几分钟,而且很容易出错,一百次出错一次算是概率低了,但是生产出错一次都是重大事件,所以我们也在思考如何通过自动化解决以上问题,如何将开发和部署分离,开发人员只关心开发,开发完提交代码,打包和部署都是后台透明的完成。以下就是我们的解决方案。 打包war包打包问题解决spring boot打war包的步骤如下 <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">
...
<packaging>war</packaging>
...
</project>
- 设置
spring-boot-starter-tomcat 范围为provided
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
- 修改spring boot的启动类,继承
SpringBootServletInitializer
public class DemoApplication extends SpringBootServletInitializer{
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DemoApplication.class);
}
}
每打包一次都要修改pom.xml 和启动类,打包完再修改回来,十分的繁琐,因为,我们提出以下整改方案 - 从
pom.xml 复制一个pom-war.xml 文件,将pom-war.xml 修改为war包配置 - 在根目录下(除了src目录外都可以)复制一份启动类的代码,修改为war包的配置方式。
- 编写shell脚本进行打包。
shell脚本打包过程为 - 备份当前启动类的java代码。
- 将war包启动类的代码替换掉当前启动类的代码。
- maven指定
pom-war.xml 文件进行打包。 - 打包结束后恢复启动类文件。
以下就是参考脚本 app-war.sh #!/usr/bin/env bash
v1=src/main/java/com/definesys/demo/DemoApplication.java
v2=war/DemoApplication.java
v3=war/DemoApplication-bak.java
cp -rf $v2 $v1
mvn clean package -Dmaven.test.skip=true -f war-pom.xml
cp -rf $v3 $v1
通过预先配置好pom文件和启动类文件,开发人员只要运行app-war.sh 脚本无需修改任何文件即可生成war包。 更优的方案以上方案pom文件和启动类文件都需要预先准备好,未实现完全的自动化,通过优化方案做到完全自动化。 - 脚本可以通过find命令搜索以
*Application.java 结尾的文件,作为启动类文件,读取文件名获取类名,通过字符串替换方式动态生成war包启动类文件。 - 在pom.xml中用注释设置好锚点,脚本通过替换锚点动态生成pom.xml文件。
- 如果不希望通过锚点实现,可以借助更高级的脚本语言,比如python对xml进行解析,再动态生成xml。
多模块打包这里的多模块指的是maven中的多模块,项目工程中的代码多模块,一个项目按功能划分模块后,在创建工程时一般也按照功能层面上的模块进行创建,这样避免一个模块代码过于庞大,也利于任务的分工,但打包却更麻烦了。 - 每个模块都是独立的spring boot程序,整合到一个包的时候会出现多个启动类,多个配置文件冲突的问题。
- 每个模块有引用相同的依赖,依赖包版本升级后,需要每个pom文件都做修改。
通过优化项目结构解决以上问题 - 父项目的pom指定spring boot的依赖和公共的依赖。
- 创建一个spring boot的子项目,作为启动项目,我们称为
start 项目。 - 其余子项目为普通的java maven项目,parent设置为第一步创建的spring boot父项目。
- start项目的pom引用其他子项目的依赖。
- 本地调试可以直接运行start的启动类,ide会自动编译其他模块并引用。
- 打包可以在父项目上进行
install 后再进入start项目进行打包,脚本参考如下
mvn clean install
cd start
mvn clean package
目录结构如下 .
├── pom.xml
├── role
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── definesys
│ │ │ └── demo
│ │ │ └── controller
│ │ │ └── RoleController.java
│ │ └── resources
├── start
│ ├── pom.xml
│ ├── src
│ │ ├── main
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ └── definesys
│ │ │ │ └── demo
│ │ │ │ └── DemoApplication.java
│ │ │ └── resources
│ │ │ └── application.properties
└── user
├── pom.xml
└── src
└── main
├── java
│ └── com
│ └── definesys
│ └── demo
│ └── controller
│ └── UserController.java
└── resources
- start项目包含包含启动类和配置文件,pom文件引用其余子项目。
start pom.xml <?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">
<parent>
<artifactId>blog0915</artifactId>
<groupId>com.definesys.demo</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>start</artifactId>
<dependencies>
<dependency>
<groupId>com.definesys.demo</groupId>
<artifactId>user</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.definesys.demo</groupId>
<artifactId>role</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 父项目parent为spring boot,引用spring boot相关依赖和各个子项目公共的依赖
父项目 pom.xml <?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>
<packaging>pom</packaging>
<modules>
<module>user</module>
<module>role</module>
<module>start</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.2.RELEASE</version>
<relativePath/>
</parent>
<groupId>com.definesys.demo</groupId>
<artifactId>blog0915</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
- 所有非start的子项目需要指定版本号并且父项目都设为根目录项目。
|