您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)在gradle項目中如何將資源文件打包到相對路徑,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
開發(fā)java application時,不管是用ant/maven/gradle中的哪種方式來構(gòu)建,通常最后都會打包成一個可執(zhí)行的jar包程序,而程序運行所需的一些資源文件(配置文件),比如jdbc.properties, log4j2.xml,spring-xxx.xml這些,可以一起打包到j(luò)ar中,程序運行時用類似classpath*:xxx.xml的去加載,大多數(shù)情況下,這樣就能工作得很好了。
但是,如果有一天,需要修正配置,比如:一個應(yīng)用上線初期,為了調(diào)試方便,可能會把log的日志級別設(shè)置低一些,比如:INFO級別,運行一段時間穩(wěn)定以后,只需要記錄WARN或ERROR級別的日志,這時候就需要修改log4j2.xml之類的配置文件,如果把配置文件打包在jar文件內(nèi)部,改起來就比較麻煩,要把重新打包部署,要么在線上,先用jar命令將jar包解壓,改好后,再打包回去,比較繁瑣。
面對這種需求,更好的方式是把配置文件放在jar文件的外部相對目錄下,程序啟動時去加載相對目錄下的配置文件,這樣改起來,就方便多了,下面演示如何實現(xiàn):(以gradle項目為例)
主要涉及以下幾點:
1、如何不將配置文件打包到j(luò)ar文件內(nèi)
既然配置文件放在外部目錄了,jar文件內(nèi)部就沒必要再重復(fù)包含這些文件了,可以修改build.gradle文件,參考下面這樣:
processResources { exclude { "**/*.*" } }
相當(dāng)于覆蓋了默認(rèn)的processResouces task,這樣gradle打包時,資源目錄下的任何文件都將排除。
2、log4j2的配置加載處理
log4j2加載配置文件時,默認(rèn)情況下會找classpath下的log4j2.xml文件,除非手動給它指定配置文件的位置,分析它的源碼,
可以找到下面這段:
org.apache.logging.log4j.core.config.ConfigurationFactory.Factory#getConfiguration(java.lang.String, java.net.URI)
public Configuration getConfiguration(final String name, final URI configLocation) { if (configLocation == null) { final String configLocationStr = this.substitutor.replace(PropertiesUtil.getProperties() .getStringProperty(CONFIGURATION_FILE_PROPERTY)); if (configLocationStr != null) { ConfigurationSource source = null; try { source = getInputFromUri(NetUtils.toURI(configLocationStr)); } catch (final Exception ex) { // Ignore the error and try as a String. LOGGER.catching(Level.DEBUG, ex); } if (source == null) { final ClassLoader loader = LoaderUtil.getThreadContextClassLoader(); source = getInputFromString(configLocationStr, loader); } if (source != null) { for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); if (types != null) { for (final String type : types) { if (type.equals("*") || configLocationStr.endsWith(type)) { final Configuration config = factory.getConfiguration(source); if (config != null) { return config; } } } } } } } else { for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); if (types != null) { for (final String type : types) { if (type.equals("*")) { final Configuration config = factory.getConfiguration(name, configLocation); if (config != null) { return config; } } } } } } } else { // configLocation != null final String configLocationStr = configLocation.toString(); for (final ConfigurationFactory factory : getFactories()) { final String[] types = factory.getSupportedTypes(); if (types != null) { for (final String type : types) { if (type.equals("*") || configLocationStr.endsWith(type)) { final Configuration config = factory.getConfiguration(name, configLocation); if (config != null) { return config; } } } } } } Configuration config = getConfiguration(true, name); if (config == null) { config = getConfiguration(true, null); if (config == null) { config = getConfiguration(false, name); if (config == null) { config = getConfiguration(false, null); } } } if (config != null) { return config; } LOGGER.error("No log4j2 configuration file found. Using default configuration: logging only errors to the console."); return new DefaultConfiguration(); }
其中常量CONFIGURATION_FILE_PROPERTY的定義為:
public static final String CONFIGURATION_FILE_PROPERTY = "log4j.configurationFile";
從這段代碼可以看出,只要在第一次調(diào)用log4j2的getLogger之前設(shè)置系統(tǒng)屬性,將其指到配置文件所在的位置即可。
3、其它一些配置文件(比如spring配置)的相對路徑加載
這個比較容易,spring本身就支持從文件目錄加載配置的能力。
綜合以上分析,可以封裝一個工具類:
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import java.io.File; public class ApplicationContextUtil { private static ConfigurableApplicationContext context = null; private static ApplicationContextUtil instance = null; public static ApplicationContextUtil getInstance() { if (instance == null) { synchronized (ApplicationContextUtil.class) { if (instance == null) { instance = new ApplicationContextUtil(); } } } return instance; } public ConfigurableApplicationContext getContext() { return context; } private ApplicationContextUtil() { } static { //加載log4j2.xml String configLocation = "resources/log4j2.xml"; File configFile = new File(configLocation); if (!configFile.exists()) { System.err.println("log4j2 config file:" + configFile.getAbsolutePath() + " not exist"); System.exit(0); } System.out.println("log4j2 config file:" + configFile.getAbsolutePath()); try { //注:這一句必須放在整個應(yīng)用第一次LoggerFactory.getLogger(XXX.class)前執(zhí)行 System.setProperty("log4j.configurationFile", configFile.getAbsolutePath()); } catch (Exception e) { System.err.println("log4j2 initialize error:" + e.getLocalizedMessage()); System.exit(0); } //加載spring配置文件 configLocation = "resources/spring-context.xml"; configFile = new File(configLocation); if (!configFile.exists()) { System.err.println("spring config file:" + configFile.getAbsolutePath() + " not exist"); System.exit(0); } System.out.println("spring config file:" + configFile.getAbsolutePath()); if (context == null) { context = new FileSystemXmlApplicationContext(configLocation); System.out.println("spring load success!"); } } }
注:這里約定了配置文件放在相對目錄resources下,而且log4j2的配置文件名為log4j2.xml,spring的入口配置文件為spring-context.xml(如果不想按這個約定來,可參考這段代碼自行修改)
有了這個工具類,mainclass入口程序上可以這么用:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; /** * Created by yangjunming on 12/15/15. * author: yangjunming@huijiame.com */ public class App { private static ApplicationContext context; private static Logger logger; public static void main(String[] args) { context = ApplicationContextUtil.getInstance().getContext(); logger = LoggerFactory.getLogger(App.class); System.out.println("start ..."); logger.debug("debug message"); logger.info("info message"); logger.warn("warn message"); logger.error("error message"); System.out.println(context.getBean(SampleObject.class)); } }
再次友情提醒:logger的實例化,一定要放在ApplicationContextUtil.getInstance().getContext();之后,否則logger在第一次初始化時,仍然嘗試會到classpath下去找log4j2.xml文件,實例化之后,后面再設(shè)置系統(tǒng)屬性就沒用了。
4、gradle 打包的處理
代碼寫完了,還有最后一個工作沒做,既然配置文件不打包到j(luò)ar里了,那就得復(fù)制到j(luò)ar包的相對目錄resources下,可以修改build.gradle腳本,讓計算機處理處理,在代替手動復(fù)制配置文件。
task pack(type: Copy, dependsOn: [clean, installDist]) { sourceSets.main.resources.srcDirs.each { from it into "$buildDir/install/$rootProject.name/bin/resources" } }
增加這個task后,直接用gradle pack 就可以實現(xiàn)打包,并自動復(fù)制配置文件到相對目錄resources目錄下了,參考下圖:
gradle pack 后,可進入build/install/config-load-demo/bin 目錄,運行./config-load-demo (windows下運行config-load-demo.bat) 查看效果,然后嘗試修改resources/log4j2.xml里的日志級別,再次運行,觀察變化 。
關(guān)于在gradle項目中如何將資源文件打包到相對路徑就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。