期望达到的效果是每次更新服务器端应用只需要更新主程序jar 依赖jar单独分离。配置文件独立存放于文件夹内,更新程序并不会覆盖已有的配置信息。

一、配置外移

1、开发环境外移

做法:在项目同级或者上级创建config文件夹放置配置文件,具体module内部application.properties通过spring.profiles.include引用外部配置。利用的是springboot加载配置顺序原理,优先同级config文件夹,然后是同级properties,继而是jar包内部的properties。

maven打包包含配置 文件 maven 打包 配置文件在外_spring boot


但是如果是用test测试用例则无法配置外移需要将配置放于test/resources

maven打包包含配置 文件 maven 打包 配置文件在外_java_02


这里附带一下springboot 测试用例写法

import com.health.AdminSrvApp;
import com.health.bean.po.UserInfo;
import com.health.main.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

/**
 * @author katasea
 * 2020/7/14 10:27
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = AdminSrvApp.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestPropertySource("classpath:application.yml")
@Slf4j
public class UserInfoServiceTest {
	@Resource
	UserInfoService userInfoService;
	@Test
	public void testSaveOrUpdate(){
			log.info("无法获取登录用户信息,模拟返回用户:test,2,test 要修改检索:LoginHandlerMethodArgumentResolver.java");
			UserInfo userInfo = new UserInfo();
			userInfo.setUserId("test");
			userInfo.setUserType(2);
			userInfo.setUserName("test2");
			userInfo.setIsAdmin(1);
			userInfo.setPhone(18650093759L);
			userInfo.setSex(1);
			userInfoService.mySaveOrUpdate(userInfo);
	}
}

也顺便附带一下logback配置文件内容

<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <contextName>admin-srv</contextName>
    <property name="LOG_PATH" value="log" />
    <!--<property name="CONSOLE_LOG_PATTERN"-->
    <!--value="%boldRed(%date{yyyy-MM-dd HH:mm:ss}) | %boldYellow(%thread) | %msg%n"/>-->
    <!-- 日志记录器,日期滚动记录 -->
    <appender name="FILEERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/admin-srv_log_error.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 归档的日志文件的路径,例如今天是2013-12-21日志,当前写的日志文件路径为file节点指定,可以将此文件与file指定文件路径设置为不同路径,从而将当前日志文件或归档日志文件置不同的目录。
            而2013-12-21的日志文件在由fileNamePattern指定。%d{yyyy-MM-dd}指定日期格式,%i指定索引 -->
            <fileNamePattern>${LOG_PATH}/error/admin-srv_log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <!-- 除按日志记录之外,还配置了日志文件不能超过2M,若超过2M,日志文件会以索引0开始,
            命名日志文件,例如log-error-2013-12-21.0.log -->
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | MDC[%X{requestId}] | %logger :%-3L| %msg%n</pattern>
            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>-->
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录info级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>error</level>
            <!--<onMatch>ACCEPT</onMatch>-->
            <!--<onMismatch>DENY</onMismatch>-->
        </filter>
    </appender>

    <!-- 日志记录器,日期滚动记录 -->
    <appender name="FILEDEBUG" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 正在记录的日志文件的路径及文件名 -->
        <file>${LOG_PATH}/admin-srv_log_debug.log</file>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/info/admin-srv_log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
        <!-- 追加方式记录日志 -->
        <append>true</append>
        <!-- 日志文件的格式 -->
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | MDC[%X{requestId}] | %logger | %msg%n</pattern>
            <charset>utf-8</charset>
        </encoder>
        <!-- 此日志文件只记录debug级别的 -->
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>debug</level>
            <!--<onMatch>ACCEPT</onMatch>-->
            <!--<onMismatch>DENY</onMismatch>-->
        </filter>
    </appender>
    <appender name="ASYNC_FILEDEBUG" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>10000</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="FILEDEBUG"/>
    </appender>
    <appender name="ASYNC_FILEERROR" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志.默认的,如果队列的80%已满,则会丢弃TRACT、DEBUG、INFO级别的日志 -->
        <discardingThreshold>0</discardingThreshold>
        <!-- 更改默认的队列的深度,该值会影响性能.默认值为256 -->
        <queueSize>10000</queueSize>
        <!-- 添加附加的appender,最多只能添加一个 -->
        <appender-ref ref="FILEERROR"/>
    </appender>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!--encoder 默认配置为PatternLayoutEncoder-->
        <encoder>
            <!--<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger Line:%-3L - %msg%n</pattern>-->
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %thread | MDC[%X{requestId}] | %msg%n</pattern>
            <!--<pattern>${CONSOLE_LOG_PATTERN}</pattern>-->
            <!--<charset>gbk</charset>-->
        </encoder>
        <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>debug</level>
        </filter>
    </appender>

    <logger name="org.springframework" level="WARN" />
    <logger name="com.health.main.mapper" level="DEBUG" />

    <!-- 生产环境下,将此级别配置为适合的级别,以免日志文件太多或影响程序性能 -->
    <root level="INFO">
        <appender-ref ref="ASYNC_FILEERROR" />
        <!--<appender-ref ref="FILEWARN" />-->
        <appender-ref ref="ASYNC_FILEDEBUG" />

        <!-- 生产环境将请stdout,testfile去掉 -->
        <appender-ref ref="STDOUT" />
    </root>
</configuration>
2、生产环境部署分离

这里按开发环境一样将配置文件放config文件夹与module同级,并在同级下编写启动脚本。

maven打包包含配置 文件 maven 打包 配置文件在外_日志文件_03


文件夹内部如下图则是lib与主jar分离的形式。具体maven如何编写下面会介绍。

maven打包包含配置 文件 maven 打包 配置文件在外_java_04


这里附带脚本写法

title 应用名称:8503/dubbo:20890
java -Xmx256M -Xms256M -jar -Dfile.encoding=gbk -Dloader.path=./admin-srv/lib,./config  ./admin-srv/admin-srv-v1.0.jar.original

配置文件夹需要与启动脚本同级,这里脚本加了限制启动内存,jar包路径等根据实际情况自己修改。

二、MAVEN打包

1、普通lib包分离

maven关键配置如下:

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>

            <resource>
                <directory>src/main/resources/mapping/*</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- jdk 版本和编译等级 -->
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
               <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
            <!--这里如果是true 打包的jar 无法用rar重新放入class文件-->
            <excludeDevtools>false</excludeDevtools>
            </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <!--不打包依赖的jar,把依赖的jar copy到lib目录,和生成的jar放在同一级目录下-->
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.health.AdminSrvApp</mainClass>
                        </manifest>

                    </archive>
                    <alias>abc</alias>
                </configuration>
            </plugin>


            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/lib</outputDirectory>
                            <overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer>
                        </configuration>
                    </execution>
                </executions>
            </plugin> 
        </plugins>
    </build>

直接用maven打包命令即可: mvn package -Dmaven.test.skip=true

打包后目录如下,拷贝lib文件夹和original轻量包到上面生产环境的具体服务文件夹下即可。

maven打包包含配置 文件 maven 打包 配置文件在外_java_05

2、自定义某些lib包不分离合并到主jar一起打包

实际中,我们需要频繁拷贝 api common 等jar来更新各个文件夹内部的lib对应的jar十分繁琐,有没有可能将经常变动的jar也合并打包到轻量包内,不经常变动的外部引用jar才放置于lib文件夹呢?这样后续更新只要更新original轻量包重新启动脚本即可。无需每次更新都拷贝大量的不变的lib文件夹外部的jar。

为了实现自定义打包则需要使用maven另外一个插件 maven部分代码如下。

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>

            <resource>
                <directory>src/main/resources/mapping/*</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- jdk 版本和编译等级 -->
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!--            <plugin>-->
            <!--                <groupId>org.springframework.boot</groupId>-->
            <!--                <artifactId>spring-boot-maven-plugin</artifactId>-->
            <!--                <configuration>-->
            <!--                    <excludeDevtools>false</excludeDevtools>-->
            <!--                </configuration>-->
            <!--            </plugin>-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <!--不打包依赖的jar,把依赖的jar copy到lib目录,和生成的jar放在同一级目录下-->
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>com.health.AdminSrvApp</mainClass>
                        </manifest>

                    </archive>
                    <alias>abc</alias>
                </configuration>
            </plugin>


            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>target/lib</outputDirectory>
                            <overWriteReleases>false</overWriteReleases>
                            <overWriteSnapshots>false</overWriteSnapshots>
                            <overWriteIfNewer>true</overWriteIfNewer>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

            <!-- 这里来实现自定义的maven打包 可以指定哪些jar要合并到original -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.8</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <target>
                                <echo>Building 描述信息 START....</echo>
                                <!-- 删除目录 -->
                                <delete dir="target/temp"/>
                                <!-- 删除目录 -->
                                <mkdir dir="target/temp"/>
                                <mkdir dir="target/temp/main"/>
                                <mkdir dir="target/temp/oth"/>

                                <!-- 复制目录文件 复制到-todir 要复制的目录-fileset -->
                                <echo>Copying jar START....</echo>

<!--                                <copy tofile="target/${project.artifactId}-${project.version}.jar.original"-->
<!--                                      file="target/${project.artifactId}-${project.version}.jar"-->
<!--                                      failοnerrοr="false" verbose="true" overwrite="true">-->
<!--                                </copy>-->

                                <!--个性化制作jar包 -->
                                <!-- 第一步 先把常用的jar挪到dir中 -->
                                <copy todir="target/temp/oth"
                                      failonerror="false" verbose="true" overwrite="true">
                                <!-- TODO 以下就是要合并到original的jar 根据自己情况编辑 还包括下面一段内容 -->
                                    <fileset dir="target/lib" includes="mall-*.jar"/>
                                    <fileset dir="target/lib" includes="core-srv-*.jar"/>
                                </copy>

                                <copy tofile="target/temp/main/${project.artifactId}-${project.version}.jar"
                                      file="target/${project.artifactId}-${project.version}.jar"
                                      failonerror="false" verbose="true" overwrite="true">
                                </copy>
                                <!-- 第二步 删除lib里面的这些常用jar -->
                                <delete>
                                <!-- TODO 以下就是要合并到original的jar 根据自己情况编辑 应该与上面定义的拷贝内容一致! -->
                                    <fileset dir="target/lib" includes="mall-*.jar"/>
                                    <fileset dir="target/lib" includes="core-srv-*.jar"/>
                                
                                </delete>
                                <!-- 第三步 解压临时文件夹的jar -->
                                <unzip dest="target/temp/oth">
                                    <fileset dir="target/temp/oth"></fileset>
                                </unzip>
                                <unzip dest="target/temp/main" overwrite="true">
                                    <fileset dir="target/temp/main"></fileset>
                                </unzip>
                                <!-- 第四步 删除temp里面的其他jar留下 主程序jar-->
                                <delete>
                                    <fileset dir="target/temp/oth" includes="*.jar"/>
                                    <fileset dir="target/temp/main" includes="*.jar"/>
                                </delete>

                                <!-- 第六步 删除temp里面的jar待会儿要压缩-->
                                <copy todir="target/temp"
                                      failonerror="false" verbose="true" overwrite="true">
                                    <fileset dir="target/temp/oth"/>
                                </copy>
                                <copy todir="target/temp"
                                      failonerror="false" verbose="true" overwrite="true">
                                    <fileset dir="target/temp/main"/>
                                </copy>
                                <delete dir="target/temp/oth"/>
                                <delete dir="target/temp/main"/>
                                <!--第七步 重新压缩一个jar -->
                                <!--                                <jar-->
                                <!--                                        jarfile="target/${project.artifactId}-${project.version}.jar.original2"-->
                                <!--                                        basedir="target/temp"-->
                                <!--                                >-->
                                <!--                                </jar>-->
                                <!--
                                    destfile	目标文件
                                    duplicate	打包方式(一般使用preserve)
                                    zipfileset	打包那些文件
                                    prefix		增加前缀(使用最佳实践)
                                -->
                                <zip destfile="target/${project.artifactId}-${project.version}.jar.original"
                                     duplicate="preserve">
                                    <zipfileset dir="target/temp" includes="**/*.*" />
                                </zip>

                                <echo>Building 描述信息 END</echo>
                            </target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>
    </build>

还是如上执行 mvn package -Dmaven.test.skip=true 打包命令
可以用rar打开 打包后的 original包,可以看到class文件已经合并打包到内部里了。