根据B站黑马李老师视频学习整理:
视频链接:https://www.bilibili.com/video/BV15b4y1a7yG?p=1&vd_source=98c00b44c5cb87c5d2ae4fccc9f2fd5c
打包
springboot的项目基于maven,打包是通过maven进行的,很简单的两种方式:
1、可以直接在idea中右侧的maven工具栏中双击“package"
2、在项目目录下使用命令行命令
打包中spring-boot-maven-plugn插件的作用
打包依赖于pom.xml文件中的插件:
如果是使用插件打成的jar包,我们可以直接放在服务器上使用命令行运行:java -jar xxx.jar。
如果没有这个插件(在pom文件中注释掉这个插件),打出来的包是不能直接运行的。使用java -jar xxx.jar 运行会报错:
所以对比一下使用这个插件和不使用插件分别打出来的包:
首先是大小:使用插件打出来的包比较大,是不使用插件打出来的将近30倍,这肯定是有什么东西。
解压之后的结构对比:
主要的区别是两个地方:
1、META-INF目录下MANIFEST.MF 这个文件的内容
主要是这些内容的差别,可以看到在使用插件打包之后的MANIFEST.MF文件中指明了启动类名,位置,类加载器,以及依赖包的位置lib
在服务器上执行java -jar xxx.jar的时候,jvm实际上就会从这个文件找到启动类,并加载相关的文件。而如果是没有使用插件打的包,没有这些信息,在运行的时候就会报那个“没有主清单属性”的问题。
2、在使用插件打成的包中,进入BOOT-INF\classes发现这个目录下的文件和未使用插件打成的包内的内容几乎一致,只有META-INF,也在插件包的外层包含了,由此可以看出,使用插件打成的包其实包含了所有未使用插件打成的包的内容。
而在BOOT-INF目录下还有另外一个目录lib,这个在未使用插件打成的包中是没有的,这就是这两种方式的第二个差别,在lib下有很多jar包,仔细看可以发现,这些jar包都是在项目中用到的依赖包。我们的程序要运行,前提是它里面用到的依赖在环境中已经存在,并且放在对应的位置,但是在一个新的环境中我们并不能保证这一点,所以当我们使用插件打包的时候,就不需要担心这点,因为它把所有的依赖包全都带上了。
打包类型:
在pom.xml文件中有一个package的标签,可以指定打成的包的类型,
//对于一个聚合工程(相当于一个父工程下有多个子工程)
<packaging>pom</packaging>
//一个独立的程序(比如我们开发的一个单体应用)或者上面的父工程下的一个子工程(多个子工程时,可以把每个子工程打成一个一个独立的jar包,可以被其他工程引用)
<packaging>jar</packaging>
//用于在容器(Tomcat、Jetty等)上部署,
<packaging>war</packaging>
在实际工作中,现在单体项目已经很少了,所以打jar包只是针对一个小的功能,把它放入一个大的项目工程中,提供相对独立的功能或者依赖功能。对于大型项目,可以借助assembly插件,将项目打成linux.tar包,部署在服务器上,很方便管理和使用。
使用assembly插件,将java项目打成linux.tar包
这块没有仔细学,只是照着别人的项目改的,先用起来完了再说:
1)在pom文件中,添加配置内容,把关于自己项目的名字,位置什么的改一下就行
<build>
<finalName>redis-lock</finalName>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<configurationDirectory>conf</configurationDirectory>
<includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
<repositoryLayout>flat</repositoryLayout>
<useWildcardClassPath>true</useWildcardClassPath>
<daemons>
<daemon>
<id>${project.build.finalName}</id>
<mainClass>com.wen.redislock.RedisLockApplication</mainClass>
<platforms>
<platform>jsw</platform>
</platforms>
<jvmSettings>
<!-- 启动内存配置 -->
<maxStackSize>128</maxStackSize>
<extraArguments>
<extraArgument>-server</extraArgument>
<extraArgument>-XX:+AggressiveOpts</extraArgument>
<extraArgument>-Xmx512M</extraArgument>
<extraArgument>-XX:+HeapDumpOnOutOfMemoryError</extraArgument>
<extraArgument>-XX:HeapDumpPath=%HOME%/logs/oom-analyse-demo.log</extraArgument>
<extraArgument>-XX:+PrintGCDetails</extraArgument>
<extraArgument>-XX:+PrintGCTimeStamps</extraArgument>
<extraArgument>-XX:+PrintHeapAtGC</extraArgument>
<extraArgument>-XX:+PrintGCCause</extraArgument>
<extraArgument>-Xloggc:%HOME%/logs/gc-analyse-demo-%t.log</extraArgument>
<extraArgument>-XX:+UseGCLogFileRotation</extraArgument>
<extraArgument>-XX:NumberOfGCLogFiles=5</extraArgument>
<extraArgument>-XX:GCLogFileSize=20M</extraArgument>
</extraArguments>
</jvmSettings>
<generatorConfigurations>
<generatorConfiguration>
<generator>jsw</generator>
<includes>
<include>aix-ppc-32</include>
<include>aix-ppc-64</include>
<include>hpux-parisc-64</include>
<include>linux-x86-32</include>
<include>linux-x86-64</include>
<include>linux-ppc-64</include>
<include>macosx-ppc-32</include>
<include>macosx-x86-universal-32</include>
<include>macosx-universal-32</include>
<include>macosx-universal-64</include>
<include>solaris-sparc-32</include>
<include>solaris-sparc-64</include>
<include>solaris-x86-32</include>
<include>windows-x86-32</include>
<include>windows-x86-64</include>
</includes>
<configuration>
<property>
<name>configuration.directory.in.classpath.first</name>
<value>conf</value>
</property>
<property>
<name>set.default.REPO_DIR</name>
<value>lib</value>
</property>
<property>
<name>wrapper.logfile</name>
<value>%HOME%/logs/redis-lock-demo.log</value>
</property>
<property>
<name>wrapper.logfile.maxsize</name>
<value>10m</value>
</property>
<property>
<name>wrapper.ntservice.interactive</name>
<value>true</value>
</property>
</configuration>
</generatorConfiguration>
</generatorConfigurations>
</daemon>
</daemons>
</configuration>
<executions>
<execution>
<id>generate-jsw</id>
<phase>package</phase>
<goals>
<goal>generate-daemons</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/assembly-linux.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<!-- 应用不部署jar包 -->
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<imageName>wen/${project.build.finalName}</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<buildArgs>
<TAR_FILE>${project.build.finalName}-linux.tar.gz</TAR_FILE>
<BIN_NAME>${project.build.finalName}</BIN_NAME>
</buildArgs>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}-linux.tar.gz</include>
</resource>
</resources>
<imageTags>
<imageTag>${project.version}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
</configuration>
</plugin>
</plugins>
</build>
2)在src/main/assembly/目录下添加assembly-linux.xml文件
文件位置:
文件内容:改一下里面与项目相关的内容
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>linux</id>
<includeBaseDirectory>false</includeBaseDirectory>
<formats>
<format>tar.gz</format>
</formats>
<fileSets>
<fileSet>
<directory>target/generated-resources/appassembler/jsw/redis-lock/bin</directory>
<outputDirectory>redis-lock/bin</outputDirectory>
<fileMode>0755</fileMode>
<includes>
<include>redis-lock</include>
<include>wrapper-linux*</include>
</includes>
</fileSet>
<fileSet>
<directory>target/generated-resources/appassembler/jsw/redis-lock/lib</directory>
<outputDirectory>redis-lock/lib</outputDirectory>
<includes>
<include>*.jar</include>
<include>libwrapper-linux*</include>
</includes>
</fileSet>
<fileSet>
<directory>target/generated-resources/appassembler/jsw/redis-lock/conf</directory>
<outputDirectory>redis-lock/conf</outputDirectory>
<includes>
<include>*</include>
</includes>
</fileSet>
<fileSet>
<directory>src/main/resources</directory>
<outputDirectory>redis-lock/conf</outputDirectory>
<filtered>true</filtered>
<excludes>
<exclude>META-INF/**</exclude>
</excludes>
</fileSet>
<fileSet>
<directory>.</directory>
<outputDirectory>redis-lock/logs</outputDirectory>
<excludes>
<exclude>**/*</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
3)在src/main/docker目录下添加Dockerfile文件(跳过这一步,这是应该是使用docker的时候用到的,暂时不用先记下)
文件位置:
文件内容:
FROM tomcat:8-jdk8
ARG TAR_FILE
ARG BIN_NAME
RUN mkdir -p /app
ADD ${TAR_FILE} /app
RUN mkdir -p /app/${BIN_NAME}/logs && \
mv /app/${BIN_NAME}/bin/${BIN_NAME} /app/${BIN_NAME}/bin/app && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
WORKDIR /app/${BIN_NAME}
ENV HOME /app
CMD ["./bin/app", "console"]
4)打包命令还是package,直接把linux.tar包上传到服务器上,打出来的包位置:
5)将打成的linux.tar,上传到服务器的指定目录下,解压之后是这个结构:
bin下是运行程序,conf下是配置文件,就是我们项目中的yaml或properties文件,lib下是依赖的jar包,logs是日志
6)我们得到这个结构之后,进入bin目录下,第一个文件就是打包插件帮我们生成的启动程序,运行这个启动程序就相当于启动我们的项目了,运行指令有:start,stop,restart。
直接运行 :./xxx start 就可以运行我们的项目了。
后期需要维护的时候,我们只需要把我们有改动的工程单独打成jar包放在这里的lib目录下,然后到bin下重新启动项目,改动的部分就可以生效了。