ResourceBundle.getBundle()默认路径及Maven项目.properties文件放置位置咨询
问题描述
在大型Java项目的小型组件单元测试中,复用第三方类TheOtherClassNoPartOfMyProject时遇到配置文件加载失败的问题。该类通过ResourceBundle读取.properties文件获取SSLContext配置,核心加载代码如下:
public class TheOtherClassNoPartOfMyProject { private ResourceBundle resourceBundle = null; public void setLocale(Locale newLocale) throws ACCatastrophicException { if (newLocale.equals(locale) && (resourceBundle != null)) { return; } locale = newLocale; try { resourceBundle = ResourceBundle.getBundle(filename, locale); } catch (MissingResourceException e) { resourceBundle = null; System.out.println("Could not locate properties file for locale '" + locale.toString() + "'"); throw new ACCatastrophicException("Could not locate " + ACProductVersion.getProductName() + " properties file for locale '" + locale.toString() + "'"); } } }
测试时抛出Could not locate properties file for locale ...错误。部署时配置文件放在应用根目录的bin文件夹可正常工作,但Maven项目无bin目录,不清楚文件放置位置。组件创建SSLContext的代码如下:
public class MyService { private static SSLContext sslContext=null; private static final String TLSV12 = "TLSv1.2"; public void createSSLContext() { KeyStore keyStore= null; KeyStore trustStore = null; InputStream kis =null; InputStream tis = null; KeyManagerFactory keyManagerFactory = null; TrustManagerFactory trustManagerFactory = null; try { constants = TheOtherClassNoPartOfMyProject.getInstance(); sslContext = SSLContext.getInstance(TLSV12); if (constants.getString("webservice.keystore") != null && !(constants.getString("webservice.keystore").isEmpty())) { keyStore = KeyStore.getInstance("JKS"); kis = new FileInputStream(constants.getString("webservce.keystore")); // 注意:此处拼写错误,应为webservice if (constants.getString("webservice.keystore_password") != null && !(constants.getString("webservice.keystore_password").isEmpty())) { String keyPassword = "changeit"; keyStore.load(kis,keyPassword.toCharArray()); keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, keyPassword.toCharArray()); } } if (constants.getString("webservice.truststore") !=null && !(constants.getString("webservice.truststore").isEmpty())) { trustStore = KeyStore.getInstance("JKS"); tis = new FileInputStream(constants.getString("webservice.truststore")); if (constants.getString("webservice.truststore_password") != null && !(constants.getString("webservice.truststore_password").isEmpty())) { String trustStorePassword = "changeit"; trustStore.load(tis, trustStorePassword.toCharArray()); } trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); } sslContext.init( keyManagerFactory!=null?keyManagerFactory.getKeyManagers():null, trustManagerFactory!=null?trustManagerFactory.getTrustManagers():null, new java.security.SecureRandom()); } catch (Exception ex) { ex.printStackTrace(); } } }
希望先确保代码与现有依赖正常协作,而非直接使用Mockito模拟,因此询问ResourceBundle.getBundle()的默认访问路径,以及Maven项目中正确的文件放置位置。
解答
1. ResourceBundle.getBundle()的默认加载路径
ResourceBundle.getBundle()是从**JVM的类路径(Classpath)**中加载资源文件,而非文件系统路径。它依赖调用该方法的类的类加载器来查找资源:
- 如果
filename是不带包名的资源名称(比如"appconfig"),则会在类路径的根目录下查找匹配的.properties文件(如appconfig.properties、appconfig_zh_CN.properties等); - 如果
filename包含包结构(比如"com.company.appconfig"),则会在类路径下对应包结构的目录中查找(即类路径下的com/company/目录下的appconfig.properties); - 加载时会优先匹配指定Locale的文件,若找不到则回退到默认的无Locale后缀的.properties文件。
2. Maven项目中的文件放置位置
针对单元测试场景,需将.properties文件放在Maven项目的src/test/resources目录下,具体分两种情况:
- 无包结构的配置文件:直接将文件放在
src/test/resources根目录(比如filename是"myapp",则放src/test/resources/myapp.properties); - 带包结构的配置文件:在
src/test/resources下创建与包名对应的目录结构,比如filename是"com.company.myapp",则创建src/test/resources/com/company/目录,将myapp.properties放入其中。
Maven在执行单元测试时,会自动将src/test/resources目录下的所有资源加入到测试类路径中,这样ResourceBundle.getBundle()就能正确加载到配置文件。
补充:部署时bin目录能正常工作,是因为部署环境将bin目录加入了应用的类路径,而Maven项目的类路径默认规则是主代码用
src/main/resources,测试代码用src/test/resources。
额外提示
你的MyService代码中有一处拼写错误:constants.getString("webservce.keystore")中的webservce应为webservice,这会导致后续读取密钥库路径失败,建议修正。
内容的提问来源于stack exchange,提问作者tarekahf

