Spring boot(4)-应用打包部署

摘自: http://blog.csdn.net/hguisu/article/details/51072683

1、Spring Boot内置web

spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动。其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat)。当然你也可以将项目打包成war包,放到独立的web容器中(Tomcat、weblogic等等),当然在此之前你要对程序入口做简单调整。

对server的几个常用的配置做个简单说明:

[plain] view plain copy

print?

  1. # 项目contextPath,一般在正式发布版本中,我们不配置
  2. server.context-path=/myspringboot
  3. # 错误页,指定发生错误时,跳转的URL。请查看BasicErrorController源码便知
  4. server.error.path=/error
  5. # 服务端口
  6. server.port=9090
  7. # session最大超时时间(分钟),默认为30
  8. server.session-timeout=60
  9. # 该服务绑定IP地址,启动服务器时如本机不是该IP地址则抛出异常启动失败,只有特殊需求的情况下才配置
  10. # server.address=192.168.16.11

Tomcat 
Tomcat为Spring Boot的默认容器,下面是几个常用配置:

pom.xml依赖配置:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--<scope>provided</scope>-->
</dependency>

[plain] view plain copy

print?

  1. # tomcat最大线程数,默认为200
  2. server.tomcat.max-threads=800
  3. # tomcat的URI编码
  4. server.tomcat.uri-encoding=UTF-8
  5. # 存放Tomcat的日志、Dump等文件的临时文件夹,默认为系统的tmp文件夹(如:C:\Users\Shanhy\AppData\Local\Temp)
  6. server.tomcat.basedir=H:/springboot-tomcat-tmp
  7. # 打开Tomcat的Access日志,并可以设置日志格式的方法:
  8. #server.tomcat.access-log-enabled=true
  9. #server.tomcat.access-log-pattern=
  10. # accesslog目录,默认在basedir/logs
  11. #server.tomcat.accesslog.directory=
  12. # 日志文件目录
  13. logging.path=H:/springboot-tomcat-tmp
  14. # 日志文件名称,默认为spring.log
  15. logging.file=myapp.log

Jetty 
如果你要选择Jetty,也非常简单,就是把pom中的tomcat依赖排除,并加入Jetty容器的依赖,如下:

[html] view plain copy

print?

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-tomcat</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-jetty</artifactId>
  15. </dependency>
  16. <dependencies>

项目构建我们使用Maven或Gradle,这将使项目依赖、jar包管理、以及打包部署变的非常方便。

2、Maven构建Spring Boot框架的可执行Jar包

在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server。单独的JAR包,然后通过Java -jar <name>.jar命令运行。

1.1 Maven

SpringBootMaven插件为Maven提供SpringBoot支持,它允许你打包可执行jar或war存档,然后就地运行应用。为了使用
它,你需要使用Maven 3.2(或更高版本)。

Maven用户可以继承spring-boot-starter-parent项目来获取合适的默认设置。该父项目提供以下特性:
1、默认编译级别为Java 1.6
2、源码编码为UTF-8
3、一个依赖管理节点,允许你省略普通依赖的 <version>标签,继承自 spring-boot-dependenciesPOM。
      合适的资源过滤
4、合适的插件配置(exec插件,surefire,Git commitID,shade)
5、针对 application.properties和application.yml 的资源过滤
6、最后一点:由于默认配置文件接收Spring风格的占位符( ${...} ),Maven  filtering改用@[email protected] 占位符(你可以使用Maven属性 resource.delimiter来覆盖它)。

1.2继承starter parent

想配置你的项目继承  spring-boot-starter-parent 只需要简单地设置parent为:

[html] view plain copy

print?

  1. <!-- Inherit defaults    from    Spring  Boot    -->
  2. <parent>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-parent</artifactId>
  5. <version>1.3.0.BUILD-SNAPSHOT</version>
  6. </parent>

注:你应该只需要在该依赖上指定Spring Boot版本。如他的starters,你可以放心的省略版本号。

 

 

1.3使用没有父POM的SpringBoot

不是每个人都喜欢继承spring-boot-starter-parentPOM。你可能需要使用公司标准parent,或你可能倾向于显式声明所有
Maven配置。
如果你不使用 spring-boot-starter-parent ,通过使用一个scope=import 的依赖,你仍能获取到依赖管理的好处:

[html] view plain copy

print?

  1. <dependencyManagement>
  2. <dependencies>
  3. <dependency>
  4. <!-- Import  dependency  management  from    Spring  Boot    -->
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-dependencies</artifactId>
  7. <version>1.3.0.BUILD-SNAPSHOT</version>
  8. <type>pom</type>
  9. <scope>import</scope>
  10. </dependency>
  11. </dependencies>
  12. </dependencyManagement>


1.4改变Java版本

spring-boot-starter-parent选择相当保守的Java兼容策略。如果你遵循我们的建议,使用最新的Java版本,你可以添加一
个 java.version属性:
<properties>
<java.version>1.8</java.version>
</properties>

1.5 使用Spring Boot Maven插件

SpringBoot包含一个Maven插件,它可以将项目打包成一个可执行jar。如果想使用它,你可以将该插件添加到<plugins>节
点处:

[html] view plain copy

print?

  1. <?xml    version="1.0"   encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <!-- ... -->
  6. <build>
  7. <plugins>
  8. <plugin>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-maven-plugin</artifactId>
  11. <version>1.3.0.BUILD-SNAPSHOT</version>
  12. <executions>
  13. <execution>
  14. <goals>
  15. <goal>repackage</goal>
  16. </goals>
  17. </execution>
  18. </executions>
  19. </plugin>
  20. </plugins>
  21. </build>
  22. </project>

注:如果使用Spring-Boot-tarter-parent pom,你只需要添加该插件而无需配置它,除非你想改变定义在partent中的设置。

该配置会在Maven生命周期的 package阶段重新打包一个jar或war。下面的示例显示在target目录下既有重新打包后的jar,
也有原始的jar:

1.6 Linux下打包方法: 

使用 mvn clean package 命令打包
如果还没有安装maven :

yum -y install apache-maven

或者单独下载安装:
wget http://apache.fayea.com/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
tar zxvf apache-maven-3.3.9-bin.tar.gz 
设置环境变量:
MVN_HOME=/usr/local/app/apache-maven-3.3.9
export PATH=$PATH:$MVN_HOME/bin

然后可以使用以下命令编译:
mvn clean package

可以追加参数 -Dmaven.test.skip=true 跳过测试

[plain] view plain copy

print?

  1. $mvn    package
  2. $ls target/*.ja

target/myproject-1.0.0.jartarget/myproject-1.0.0.jar.original

1.6 使用Eclipse下打包方法:

打开maven插件的maven package,就可以打包了:

打包出来的文件:

如果不包含像上面那样的<execution/>,你可以自己运行该插件(但只有在package目标也被使用的情况)。例如:

[plain] view plain copy

print?

  1. $   mvn package spring-boot:repackage
  2. $   ls  target/*.jar

target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
如果使用一个里程碑或快照版本,你还需要添加正确的pluginRepository元素:

[html] view plain copy

print?

  1. <pluginRepositories>
  2. <pluginRepository>
  3. <id>spring-snapshots</id>
  4. <url>http://repo.spring.io/snapshot</url>
  5. </pluginRepository>
  6. <pluginRepository>
  7. <id>spring-milestones</id>
  8. <url>http://repo.spring.io/milestone</url>
  9. </pluginRepository>
  10. </pluginRepositories>

打包可执行jar和war文件

一旦spring-boot-maven-plugin被包含到你的pom.xml中,它就会自动尝试使用spring-boot:repackage目标重写存档以使它们能够执行。为了构建一个jar或war,你应该使用常规的packaging元素配置你的项目:

[html] view plain copy

print?

  1. <?xml    version="1.0"   encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <!-- ... -->
  5. <packaging>jar</packaging>
  6. <!-- ... -->
  7. </project>

生成的存档在 package 阶段会被SpringBoot增强。你想启动的main类即可以通过指定一个配置选项,也可以通过为manifest添加一个Main-Class属性这种常规的方式实现。如果你没有指定一个main类,该插件会搜索带有publicstaticvoidmain(String[]args)方法的类。

为了构建和运行一个项目的artifact,你可以输入以下命令:

[plain] view plain copy

print?

  1. $   mvn package
  2. $   java    -jar    target/spring-boot01-1.0-SNAPSHOT.jar

这种方式,只要控制台关闭,服务就不能访问了。下面我们使得 jar 包在后台运行:

java -jar spring-boot01-1.0-SNAPSHOT.jar > log.file 2>&1 &

为了构建一个即是可执行的,又能部署到一个外部容器的war文件,你需要标记内嵌容器依赖为"provided",例如:

[html] view plain copy

print?

  1. <?xml    version="1.0"   encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <!-- ... -->
  5. <packaging>war</packaging>
  6. <!-- ... -->
  7. <dependencies>
  8. <dependency>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-web</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-tomcat</artifactId>
  15. <scope>provided</scope>
  16. </dependency>
  17. <!-- ... -->
  18. </dependencies>
  19. </project>

4、打包为单个jar时,spring boot的启动方式

maven打包之后,会生成两个jar文件:

demo-0.0.1-SNAPSHOT.jar demo-0.0.1-SNAPSHOT.jar.original

其中demo-0.0.1-SNAPSHOT.jar.original是默认的maven-jar-plugin生成的包。

demo-0.0.1-SNAPSHOT.jar是spring boot maven插件生成的jar包,里面包含了应用的依赖,以及spring boot相关的类。下面称之为fat jar。

先来查看spring boot打好的包的目录结构(不重要的省略掉):

[plain] view plain copy

print?

  1. ├── META-INF
  2. │   ├── MANIFEST.MF
  3. ├── application.properties
  4. ├── com
  5. │   └── example
  6. │       └── SpringBootDemoApplication.class
  7. ├── lib
  8. │   ├── aopalliance-1.0.jar
  9. │   ├── spring-beans-4.2.3.RELEASE.jar
  10. │   ├── ...
  11. └── org
  12. └── springframework
  13. └── boot
  14. └── loader
  15. ├── ExecutableArchiveLauncher.class
  16. ├── JarLauncher.class
  17. ├── JavaAgentDetector.class
  18. ├── LaunchedURLClassLoader.class
  19. ├── Launcher.class
  20. ├── MainMethodRunner.class
  21. ├── ...

依次来看下这些内容。

MANIFEST.MF

[plain] view plain copy

print?

  1. Manifest-Version: 1.0
  2. Start-Class: com.example.SpringBootDemoApplication
  3. Implementation-Vendor-Id: com.example
  4. Spring-Boot-Version: 1.3.0.RELEASE
  5. Created-By: Apache Maven 3.3.3
  6. Build-Jdk: 1.8.0_60
  7. Implementation-Vendor: Pivotal Software, Inc.
  8. Main-Class: org.springframework.boot.loader.JarLauncher

可以看到有Main-Class是org.springframework.boot.loader.JarLauncher ,这个是jar启动的Main函数。

还有一个Start-Class是com.example.SpringBootDemoApplication,这个是我们应用自己的Main函数

[plain] view plain copy

print?

  1. @SpringBootApplication
  2. public class SpringBootDemoApplication {
  3. public static void main(String[] args) {
  4. SpringApplication.run(SpringBootDemoApplication.class, args);
  5. }
  6. }

com/example 目录

这下面放的是应用的.class文件。

lib目录

这里存放的是应用的Maven依赖的jar包文件。 
比如spring-beans,spring-mvc等jar。

org/springframework/boot/loader 目录

这下面存放的是Spring boot loader的.class文件。

启动:

我们直接启动:java -jar demo-0.0.1-SNAPSHOT.jar 

5、Maven添加本地Jar包

我们有时候项目依赖外部的jar,我们使用Eclipse开发的时候我们直接通过build path添加jar就可以,但是使用mvn 打包的时候就会缺少这个包。

1. 使用system scope

我们直接引入rabbitmq-client.jar。这个方式比较灵活,到新的服务器上,无需做额外的操作。

[html] view plain copy

print?

  1. <dependency>
  2. <groupId>rabbitmq.client</groupId>
  3. <artifactId>rabbitmq.client</artifactId>
  4. <version>3.0</version>
  5. <scope>system</scope>
  6. <systemPath>${basedir}/src/main/WEB-INF/lib/rabbitmq-client.jar</systemPath>
  7. </dependency>

1、groupId和artifactId以及version都是可以随便填写的 ,scope必须填写为system,而systemPath我们现在我们jar包的目录地址就可以了

2、${basedir}就是项目根目录

2. 将jar包安装到本地repository中

这个需要在新机器上执行mvn install:install-file命令。

[html] view plain copy

print?

  1. mvn install:install-file
  2. -Dfile= jar文件所存放的地址
  3. -DgroupId= jar文件所属的group:包名
  4. -DartifactId=  jar的项目名 名称,一般就是去掉后缀的文件名
  5. -Dversion=版本号
  6. -Dpackaging=jar:此包的打包形式,就是jar
  7. -DgeneratePom=true

例如执行命令:
mvn install:install-file -Dfile=D:\JAR_LIB\rabbitmq-client.jar -DgroupId=com.rabbitmq -DartifactId=client -Dversion=3.5.0 -Dpackaging=jar  -DgeneratePom=true -DcreateChecksum=true

在项目中引用:

[html] view plain copy

print?

  1. <dependency>
  2. <groupId>com.rabbitmq</groupId>
  3. <artifactId>client</artifactId>
  4. <version>3.5.0</version>
  5. </dependency>

3、添加 in project repository

设置项目的库目录

<repository>
    <id>in-project</id>
    <name>In Project Repo</name>
    <url>file://${project.basedir}/lib</url>
</repository>

添加依赖:

<dependency>
    <groupId>com.rabbitmq</groupId>
    <artifactId>client</artifactId>
    <version>3.5.0</version>
</dependency>

jar包及路径必须严格遵循格式:

/groupId/artifactId/version/artifactId-verion.jar
本例中: lib/com/rabbitmq/client/3.5.0/rabbitmq-client-3.5.0.jar

6、部署到javaEE容器

修改启动类,继承 SpringBootServletInitializer 并重写 configure 方法

[java] view plain copy

print?

  1. public class SpringBootSampleApplication extends SpringBootServletInitializer{
  2. private static final Logger logger = LoggerFactory.getLogger(SpringBootSampleApplication.class);
  3. @Override
  4. protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
  5. return builder.sources(this.getClass());
  6. }
  7. }

修改pom文件中jar 为 war

[java] view plain copy

print?

  1. <!-- <packaging>jar</packaging> -->
  2. <packaging>war</packaging>

修改pom,排除tomcat插件

[java] view plain copy

print?

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-web</artifactId>
  4. <exclusions>
  5. <exclusion>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-tomcat</artifactId>
  8. </exclusion>
  9. </exclusions>
  10. </dependency>

打包部署到容器

7、热部署

在我们开发过程中,我们需要经常修改,为了避免重复启动项目,我们可以启用热部署。
Spring-Loaded项目提供了强大的热部署功能,添加/删除/修改 方法/字段/接口/枚举 等代码的时候都可以热部署,速度很快,很方便。
想在Spring Boot中使用该功能非常简单,就是在spring-boot-maven-plugin插件下面添加依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>springloaded</artifactId>
        <version>1.2.5.RELEASE</version>
    </dependency>
</dependencies>
添加以后,通过mvn spring-boot:run启动就支持热部署了。

注意:使用热部署的时候,需要IDE编译类后才能生效,你可以打开自动编译功能,这样在你保存修改的时候,类就自动重新加载了。

8、使用Profile区分环境

application.properties区分环境

spring boot 可以在 “配置文件”、“Java代码类”、“日志配置” 中来配置profile区分不同环境执行不同的结果

1、配置文件 
使用配置文件application.yml 和 application.properties 有所区别 
以application.properties 为例,通过文件名来区分环境 application-{profile}.properties

application.properties

app.name=MyApp
server.port=8080
spring.profiles.active=dev

application-dev.properties

server.port=8081

application-stg.properties

server.port=8082

在启动程序的时候通过添加 –spring.profiles.active={profile} 来指定具体使用的配置 
例如我们执行 java -jar demo.jar –spring.profiles.active=dev 那么上面3个文件中的内容将被如何应用? 
Spring Boot 会先加载默认的配置文件,然后使用具体指定的profile中的配置去覆盖默认配置。

app.name 只存在于默认配置文件 application.properties 中,因为指定环境中不存在同样的配置,所以该值不会被覆盖 
server.port 默认为8080,但是我们指定了环境后,将会被覆盖。如果指定stg环境,server.port 则为 8082 
spring.profiles.active 默认指定dev环境,如果我们在运行时指定 –spring.profiles.active=stg 那么将应用stg环境,最终 server.port 的值为8082

Maven环境配置
   项目工程统一使用maven的profile插件定义不同的项目构建环境(dev, alpha, beta, prod),通过filter插件为不同环境下的配置项注入对应的参数值来实现动态配置目标。
2.3.1定义profile
在POM.xml中配置四个profile,对应项目所处的四个不同的环境-dev, alpha, beta, prod, profile的id属性即为每个环境赋予一个唯一的标示,元素的内容则是以key-value的形式出现的键值对,如我们定义了一个变量,其值在不同的环境下(不同id)被赋予了不同的值(dev, test, pre-prod, prod),要激活不同的环境打包,我们可以在命令行通过mvn package –P${profileId}来让其运行,为了开发便利,默认激活的是dev开发环境,即开发人员不需要通过命令行手动输入-p参数也能运行dev环境的打包。
 <profile>
            <!-- 本地参数 -->
            <id>dev</id>
            <properties>
<server.port>8081</server.port>
<server.address>0.0.0.0</server.address>
<profileActive>dev</profileActive>
            </properties>
<build>
<filters>
<filter>
<groupId>${basedir}/src/main/resources/dev.properties</groupId>
</filter>
 </profile>

9、创建一个Linux 应用的sh脚本

下面几个脚本仅供参考:

打包:clean.sh

[html] view plain copy

print?

  1. #0、check user
  2. TIME_STAMP=`date +%Y%m%d%H%M`
  3. WHO=`whoami`
  4. if [ "$WHO" != ‘www‘ ]; then
  5. echo ‘current user is not www‘
  6. echo ‘exit‘
  7. exit
  8. fi
  9. CODE_HOME=/home/www/app
  10. PROJECTNAME=qrealtime
  11. cd $CODE_HOME/$PROJECTNAME
  12. git pull
  13. mvn clean package
  14. pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk ‘{print $2}‘ `
  15. if [ $pid != "" ]; then
  16. echo "App  is  running  and pid=$pid"
  17. else
  18. echo "App is not  running."
  19. fi

start.sh

[html] view plain copy

print?

  1. #0、check user
  2. TIME_STAMP=`date +%Y%m%d%H%M`
  3. WHO=`whoami`
  4. if [ "$WHO" != ‘www‘ ]; then
  5. echo ‘current user is not www‘
  6. echo ‘exit‘
  7. exit
  8. fi
  9. CODE_HOME=/home/www/app
  10. PROJECTNAME=qrealtime
  11. cd $CODE_HOME/$PROJECTNAME
  12. pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk ‘{print $2}‘`
  13. if [ $pid ]; then
  14. echo "App  is  running  and pid=$pid"
  15. else
  16. nohup java -jar $CODE_HOME/$PROJECTNAME/target/$<span style="font-family: ‘microsoft yahei‘;">PROJECTNAME</span><span style="font-family: ‘microsoft yahei‘;">-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &</span>
  17. fi

stop.sh

[html] view plain copy

print?

  1. #0、check user
  2. TIME_STAMP=`date +%Y%m%d%H%M`
  3. WHO=`whoami`
  4. if [ "$WHO" != ‘www‘ ]; then
  5. echo ‘current user is not www‘
  6. echo ‘exit‘
  7. exit
  8. fi
  9. CODE_HOME=/home/www/app
  10. PROJECTNAME=qrealtime
  11. cd $CODE_HOME/$PROJECTNAME
  12. pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk ‘{print $2}‘ `
  13. if [ $pid ]; then
  14. echo "App  is  running  and pid=$pid"
  15. kill -9 $pid
  16. if [[ $? -eq 0 ]];then
  17. echo "sucess to stop $PROJECTNAME "
  18. else
  19. echo "fail to stop $PROJECTNAME "
  20. fi
  21. fi

restart

[html] view plain copy

print?

  1. #0、check user
  2. TIME_STAMP=`date +%Y%m%d%H%M`
  3. WHO=`whoami`
  4. if [ "$WHO" != ‘www‘ ]; then
  5. echo ‘current user is not www‘
  6. echo ‘exit‘
  7. exit
  8. fi
  9. CODE_HOME=/home/www/app
  10. PROJECTNAME=qrealtime
  11. cd $CODE_HOME/$PROJECTNAME
  12. pid=`ps -ef |grep $PROJECTNAME |grep -v "grep" |awk ‘{print $2}‘ `
  13. if [ $pid ]; then
  14. echo "App  is  running  and pid=$pid"
  15. kill -9 $pid
  16. fi
  17. nohup java -jar $CODE_HOME/$PROJECTNAME/target/$PROJECTNAME-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &

10、Spring Boot应用的docker化

首先看Spring Boot应用程序的Docker化,由于Spring Boot内嵌了tomcat、Jetty等容器,因此我们对docker镜像的要求就是需要java运行环境。我的应用代码的的Dockerfile文件如下:

#基础镜像:仓库是java,标签用8u66-jdk
FROM java:8u66-jdk
#当前镜像的维护者和联系方式
MAINTAINER duqi [email protected]
#将打包好的spring程序拷贝到容器中的指定位置
ADD target/bookpub-0.0.1-SNAPSHOT.jar /opt/bookpub-0.0.1-SNAPSHOT.jar
#容器对外暴露8080端口
EXPOSE 8080
#容器启动后需要执行的命令
CMD java -Djava.security.egd=file:/dev/./urandom -jar /opt/bookpub-0.0.1-SNAPSHOT.jar

因为目前的示例程序比较简单,这个dockerfile并没有在将应用程序的数据存放在宿主机上。如果你的应用程序需要写文件系统,例如日志,最好利用VOLUME /tmp命令,这个命令的效果是:在宿主机的/var/lib/docker目录下创建一个临时文件并把它链接到容器中的/tmp目录。

把这个Dockerfile放在项目的根目录下即可,后续通过docker-compose build统一构建:基础镜像是只读的,然后会在该基础镜像上增加新的可写层来供我们使用,因此java镜像只需要下载一次。

docker-compose是用来做docker服务编排,参看《Docker从入门到实践》中的解释:

Compose 项目目前在 Github 上进行维护,目前最新版本是 1.2.0。Compose 定位是“defining and running complex applications with Docker”,前身是 Fig,兼容 Fig 的模板文件。

Dockerfile 可以让用户管理一个单独的应用容器;而 Compose 则允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 project,即项目),例如一个 Web 服务容器再加上后端的数据库服务容器等。

单个docker用起来确实没什么用,docker技术的关键在于持续交付,通过与jekins的结合,可以实现这样的效果:开发人员提交push,然后jekins就自动构建并测试刚提交的代码,这就是我理解的持续交付。

11、守护进程启动

使用java命令运行应用非常简单,但是通常我们都是通过ssh命令连接到服务器并运行它,一旦ssh连接断开,那么由它fork的java子进程也就随之销毁了。所以我们必须借助工具将应用作为服务运行在服务器上:

Systemd

systemd 是Linux 下的一款系统和服务管理器。可以为Spring Boot应用编写启动脚本:

[java] view plain copy

print?

  1. [Unit]
  2. Description=Spring Boot Application
  3. [Service]
  4. ExecStart=/usr/bin/java -jar location_of_jar_file.jar --spring.config.location=location_of_config.properties --spring.profiles.active=profile
  5. User=${your expected user}
  6. [Install]
  7. WantedBy=multi-user.target

Supervisord

Supervisord配置:

[java] view plain copy

print?

  1. [program:app]
  2. command=/usr/bin/java -jar location_of_jar_file.jar --spring.config.location=location_of_config.properties --spring.profiles.active=profile
  3. user=${your expected user}
  4. autostart=true
  5. autorestart=true
  6. startsecs=10
  7. startretries=3

12、生产环境运维支持

与开发和测试环境不同的是,当应用部署到生产环境时,需要各种运维相关的功能的支持,包括性能指标、运行信息和应用管理等。所有这些功能都有很多技术和开源库可以实现。Spring Boot 对这些运维相关的功能进行了整合,形成了一个功能完备和可定制的功能集,称之为 Actuator。只需要在 POM 文件中增加对 “org.springframe.boot:spring-boot-starter-actuator” 的依赖就可以添加 Actuator。Actuator 在添加之后,会自动暴露一些 HTTP 服务来提供这些信息。这些 HTTP 服务的说明如表 2

Spring Boot Actuator 所提供的 HTTP 服务
名称 说明 是否包含敏感信息
autoconfig 显示 Spring Boot 自动配置的信息。
beans 显示应用中包含的 Spring bean 的信息。
configprops 显示应用中的配置参数的实际值。
dump 生成一个 thread dump。
env 显示从 ConfigurableEnvironment 得到的环境配置信息。
health 显示应用的健康状态信息。
info 显示应用的基本信息。
metrics 显示应用的性能指标。
mappings 显示 Spring MVC 应用中通过“
@RequestMapping”添加的路径映射。
shutdown 关闭应用。
trace 显示应用相关的跟踪(trace)信息。

对于表中的每个服务,通过访问名称对应的 URL 就可以获取到相关的信息。如访问“/info”就可以获取到 info 服务对应的信息。服务是否包含敏感信息说明了该服务暴露出来的信息是否包含一些比较敏感的信息,从而确定是否需要添加相应的访问控制,而不是对所有人都公开。所有的这些服务都是可以配置的,比如通过改变名称来改变相应的 URL。下面对几个重要的服务进行介绍。

health 服务

Spring Boot 默认提供了对应用本身、关系数据库连接、MongoDBRedis 和 Rabbit MQ 的健康状态的检测功能。当应用中添加了 DataSource 类型的 bean 时,Spring Boot 会自动在 health 服务中暴露数据库连接的信息。应用也可以提供自己的健康状态信息,如代码清单 7 所示。

health 服务
@Component
public class AppHealthIndicator implements HealthIndicator {
 @Override
 public Health health() {
 return Health.up().build();
 }
}

应用只需要实现 org.springframework.boot.actuate.health.HealthIndicator 接口,并返回一个 org.springframework.boot.actuate.health.Health 对象,就可以通过 health 服务来获取所暴露的信息。health 服务返回的结果

{"status":"UP","app":{"status":"UP"},"db":{"status":"UP","database":"HSQL Database Engine","hello":1}}

info 服务

info 服务所暴露的信息是完全由应用来确定的。应用中任何以“info.”开头的配置参数会被自动的由 info 服务来暴露。只需要往 application.properties 中添加以“info.”开头的参数即可,如:

info.app_name=My First Spring Boot Application
info.app_version=1.0.0

当访问“/info”时,访问的 JSON 数据:

{"app_name":"My First Spring Boot Application","app_version":"1.0.0"}

metrics 服务

当访问 metrics 服务时,可以看到 Spring Boot 通过 SystemPublicMetrics 默认提供的一些系统的性能参数值,包括内存、CPU、Java 类加载和线程等的基本信息。应用可以记录其他所需要的信息。Spring Boot 默认提供了两种类型的性能指标记录方式:gauge 和 counter。gauge 用来记录单个绝对数值,counter 用来记录增量或减量值。比如在一个 Web 应用中,可以用 counter 来记录当前在线的用户数量。当用户登录时,把 counter 的值加 1;当用户退出时,把 counter 的值减 1。

示例:

@RestController
public class GreetingsController {
 @Autowired
 private CounterService counterService;
 @RequestMapping("/greet")
 public String greet() {
 counterService.increment("myapp.greet.count");
 return "Hello!";
 }
}

上面代码添加了对 Spring Boot 提供的 CounterService 的依赖。当 greet 方法被调用时,会把名称为“myapp.greet.count”的计数器的值加 1。也就是当用户每次访问“/greet”时,该计算器就会被加 1。除了 CounterService 之外,还可以使用 GaugeService 来记录绝对值。

时间: 2024-10-26 12:38:14

Spring boot(4)-应用打包部署的相关文章

Spring Boot(十二):Spring Boot 如何测试打包部署

有很多网友会时不时的问我, Spring Boot 项目如何测试,如何部署,在生产中有什么好的部署方案吗?这篇文章就来介绍一下 Spring Boot 如何开发.调试.打包到最后的投产上线. 开发阶段 单元测试 在开发阶段的时候最重要的是单元测试了, Spring Boot 对单元测试的支持已经很完善了. 1.在 pom 包中添加 spring-boot-starter-test 包引用 <dependency> <groupId>org.springframework.boot&

Spring Boot 简单的打包部署

Spring Boot 支持使用 Jar 内嵌 Web 服务器(Tomcat)的方式发布,也支持生成 war 包放在外置的 web 服务器运行. 1.使用 Jar 发布应用 配置步骤: ① pom.xml 要显示加入插件 org.springframework.boot,否则无法产生 jar 清单文件,导致打出来的 jar 无法使用命令运行. 1 <build> 2 <plugins> 3 <plugin> 4 <groupId>org.springfram

Spring Boot Tomcat 容器化部署实践与总结

在平时的工作和学习中经常会构建简单的web应用程序.如果只是HelloWorld级别的程序,使用传统的Spring+SpringMVC框架搭建得话会将大部分的时间花费在搭建框架本身上面,比如引入SpringMVC,配置DispatcheherServlet等.并且这些配置文件都差不多,重复这些劳动似乎意义不大.所以使用Springboot框架来搭建简单的应用程序显得十分的便捷和高效. 前两天在工作中需要一个用于测试文件下载的简单web程序,条件是使用Tomcat Docker Image作为载体

Spring Boot将WAR文件部署到Tomcat

在本文中,将演示如何将Spring Boot WAR文件部署到Tomcat servlet容器中. 对于Spring Boot WAR部署,需要执行三个步骤: 扩展SpringBootServletInitializer 根据提供标记嵌入式servlet容器. 更新包装为 War 测试工具: Spring Boot 1.4.2.RELEASE Tomcat 8.5.9 Maven 3 注意在Spring Boot中,具有嵌入服务器解决方案的最终可执行JAR文件可能不适合所有生产环境,特别是部署团

如何把kotlin+spring boot开发的项目部署在tomcat上

本文只讲部署过程,你首先要保证你的程序能在IDE里跑起来: 先看看你的application.properties中设置的端口号与你服务器上tomcat的端口号是否一致 server.port=80 (我现在不确定此配置是否会影响部署) 看看你的应用程序的入口函数 @SpringBootApplication@EnableAutoConfiguration(exclude = arrayOf(DataSourceAutoConfiguration::class))class JnaApplica

Spring Boot 2.0 热部署指南

Spring Boot 2.0 支持热部署,实现方法很简单 Spring Boot 2.0 有几种热重载的选项. 推荐的方法是使用spring-boot-devtools 因为它提供了额外的开发时间功能,例如支持快速应用程序重启和LiveReload以及合理的开发时配置(如模板缓存). Devtools通过监视类路径的变化来工作. 这意味着静态资源更改必须"建立",以使更改生效. 默认情况下,当您保存更改时,这会在Eclipse中自动发生. 在IntelliJ IDEA中,Make P

Spring Boot 2构建可部署的war包

默认情况下Spring Boot使用了内嵌的Tomcat服务器,项目最终被打成jar包运行,每个jar包可以被看作一个独立的Web服务器.传统的Web开发,一般会将Web应用打成一个war包,然后将其部署到Web服务器中运行.Spring Boot也支持传统的部署模式. 开发环境:IntelliJ IDEA 2019.2.2Spring Boot版本:2.1.8 1.新建一个名称为demo的Spring Boot项目. 2.修改pom.xml文件 下面粗体部分为所加代码,注释掉原来的build节

spring boot 使用maven打包删除配置文件

spring boot 项目使用maven打包 项目条件: *.properties放在jar包外面使其方便动态实时配置信息 *.properties在jar包内不允许让其存在(实际是config优先于jar包内的配置文件) 动态指定生成环境而配置文件(转微服务架构内设计) 解决办法 项目服务器jar包所在目录下,新建config文件夹,直接nohup启动即可 maven打包剔除*.properties # build下配置 <resources> <resource> <f

spring boot项目进行war部署,对于静态资源无法访问的问题

记录下jar和war部署方式随意切换部署的一个解决方案,对于如何修改为自定义的目录,这边未说明. 在spring boot开发时一般是直接application运行的(与jar部署一样),因此使用jar部署的时候可以直接运行,静态资源都可以访问: 如果我们需要进行war方式部署呢,静态资源有可能就方法不到,因为war方式部署的访问方式和jar的不同需要带上项目名称: 例如: jar部署:http://localhost:8080/index.html war部署:http://localhost