期望达到的效果是每次更新服务器端应用只需要更新主程序jar 依赖jar单独分离。配置文件独立存放于文件夹内,更新程序并不会覆盖已有的配置信息。
一、配置外移
1、开发环境外移
做法:在项目同级或者上级创建config文件夹放置配置文件,具体module内部application.properties通过spring.profiles.include引用外部配置。利用的是springboot加载配置顺序原理,优先同级config文件夹,然后是同级properties,继而是jar包内部的properties。
但是如果是用test测试用例则无法配置外移需要将配置放于test/resources
这里附带一下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同级,并在同级下编写启动脚本。
文件夹内部如下图则是lib与主jar分离的形式。具体maven如何编写下面会介绍。
这里附带脚本写法
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轻量包到上面生产环境的具体服务文件夹下即可。
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文件已经合并打包到内部里了。