1.ServletContext方式
采用ServletContext读取配置文件realpath,然后通过文件流读出来。
优点:可以读取任意位置的文件
采用文件流读取,所以可以读取不同格式的文件
缺点:不能在servlet外面读取配置文件
实现:
package com.xunjie.common.utils; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.Properties; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Profile { // 采用ServletContext读取配置文件的realpath,然后通过文件流读取出来 public void readProfileByServletContext(HttpServletRequest request, HttpServletResponse response) { // 通过servletcontext读取到文件路径 String realPath = request.getServletContext().getRealPath("jdbc.properties"); //InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream InputStreamReader reader; //Properties类,主要用于读取Java的配置文件 Properties props = new Properties(); try { // 建议使用Reader来读,因为reader体系中有个InputStreamReader可以指定编码 reader = new InputStreamReader(new FileInputStream(realPath), "utf-8"); // load ( InputStream inStream)方法 // 从输入流中读取属性列表(键和元素对)。 通过对指定的文件(比如说上面的jdbc.properties文件)进行装载来获取该文件中的所有键 - 值对。 以供 getProperty ( String key) 来搜索。 props.load(reader); } catch (Exception e) { e.printStackTrace(); } // getProperty ( String key)方法,用指定的键在此属性列表中搜索属性。也就是通过参数 key ,得到 key 所对应的 value。 String jdbcUrl = props.getProperty("url"); System.out.println(jdbcUrl); System.out.println(realPath); } }
使用Junit测试输出结果
Junit使用参考:https://blog.csdn.net/qq_37725650/article/details/79409589
package com.xunjie.test; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.xunjie.common.utils.Profile; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:spring.xml" }) public class ProfileTest { private MockHttpServletRequest request; private MockHttpServletResponse response; @Before public void setUp() { request = new MockHttpServletRequest(); request.setCharacterEncoding("UTF-8"); response = new MockHttpServletResponse(); } @Test public void test() { System.err.println("-----测试开始-start-----"); Profile profile = new Profile(); profile.readProfileByServletContext(request, response); System.err.println("-----测试结束-end-----"); } }
测试结果:
-----测试开始-start----- jdbc:mysql://127.0.0.1:3306/yeebi?useUnicode=true&&characterEncoding=UTF-8 E:\WorkSpace\xunjie\xunjie\target\classes\jdbc.properties -----测试结束-end-----
2.通过ResourceBundle类获取配置文件资源
优点:1可以以全限定类名的方式加载资源2可以在非web应用里加载资源
缺点:只能加载类下面的资源文件,且只能读取properties文件
/** * @Title: getProfileByResourceBundle * @Description: 通过ResourceBundle类获取配置文件资源 * @param propertyName 配置文件名称 * 调用方式: * 1.配置文件放在resource源包下,不用加后缀 * PropertiesUtil.getProfileByResourceBundle("message"); * 2.放在包里面的 * PropertiesUtil.getProfileByResourceBundle("com.test.message"); * @return Map<String,String> 以Map键值对方式返回配置文件内容 */ public static Map<String, String> getProfileByResourceBundle(String propertyName) { // 获得资源包 ResourceBundle rb = ResourceBundle.getBundle(propertyName.trim()); // 通过资源包拿到所有的key Enumeration<String> allKey = rb.getKeys(); Map<String, String> profileMap = new HashMap<String, String>(); // 遍历key 得到 value while (allKey.hasMoreElements()) { String key = allKey.nextElement(); String value = (String) rb.getString(key); //将文件内容存入map profileMap.put(key, value); } return profileMap; }
测试运行结果:
public static void main(String[] args) { //我的文件直接放在了src下,所以直接传入文件名称就可以了 Map<String, String> profileMap = Profile.getProfileByResourceBundle("jdbc"); String jdbcUrl = profileMap.get("url"); System.out.println(jdbcUrl); }
控制台输出: jdbc:mysql://127.0.0.1:3306/yeebi?useUnicode=true&&characterEncoding=UTF-83.通过ClassLoader方式进行读取
/** * @Title: getProfileByClassLoader * @Description: 采用ClassLoader(类加载器)方式进行读取配置信息 * @return Map<String,Object> 以Map键值对方式返回配置文件内容 * 优点:可以在非Web应用中读取配置资源信息,可以读取任意的资源文件信息 * 缺点:只能加载类classes下面的资源文件 * @throws */ public static Map<String, Object> getProfileByClassLoader() { // 通过ClassLoader获取到文件输入流对象 // 配置文件放在resource源包下,直接写文件名即可,需要后缀名"jdbc.properties" // 放在包里面的,需要写上包路径,例如:在test包下"com/test/jdbc.properties"),Profile为当前所在类类名 InputStream in = Profile.class.getClassLoader().getResourceAsStream("jdbc.properties"); // 获取文件的位置 String filePath = Profile.class.getClassLoader().getResource("jdbc.properties").getFile(); System.out.println(filePath); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); Properties props = new Properties(); Map<String, Object> profileMap = new HashMap<String, Object>(); try { props.load(reader); for (Object key : props.keySet()) { profileMap.put(key.toString(), props.getProperty(key.toString())); } } catch (IOException e) { e.printStackTrace(); } return profileMap; }
测试运行结果:
public static void main(String[] args) { Map<String, Object> profileMap = Profile.getProfileByClassLoader(); System.out.println(profileMap.get("url")); } 控制台输出: /E:/WorkSpace/xunjie/xunjie/target/classes/jdbc.properties jdbc:mysql://127.0.0.1:3306/yeebi?useUnicode=true&&characterEncoding=UTF-8
4.使用Sping提供的PropertiesLoaderUtils类读取配置文件
当然需要导入spring核心包
/** * @Title: getProfileByPropertiesLoaderUtils * @Description: Spring 提供的 PropertiesLoaderUtils 允许您直接通过基于类路径的文件地址加载属性资源 * 最大的好处就是:实时加载配置文件,修改后立即生效,不必重启 * @return Map<String,Object> */ public static Map<String, Object> getProfileByPropertiesLoaderUtils() { Properties props = new Properties(); Map<String, Object> profileMap = new HashMap<String, Object>(); try { props = PropertiesLoaderUtils.loadAllProperties("jdbc.properties"); for (Object key : props.keySet()) { profileMap.put(key.toString(), props.getProperty(key.toString())); } } catch (IOException e) { System.out.println(e.getMessage()); } return profileMap; }
测试运行结果:
public static void main(String[] args) { Map<String, Object> profileMap = Profile.getProfileByPropertiesLoaderUtils(); System.out.println(profileMap.get("url")); } 控制台输出: jdbc:mysql://127.0.0.1:3306/yeebi?useUnicode=true&&characterEncoding=UTF-8
5.修改配置文件
只是修改了classes下的文件,源文件并没有改变。
/** * 传递键值对的Map,更新properties文件 * * @param fileName * 文件名(放在resource源包目录下),需要后缀 * @param keyValueMap * 键值对Map */ public static void updateProperties(String fileName, Map<String, String> keyValueMap) { // 输入流 // InputStream // inputStream=PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName); // 获取文件的路径 String filePath = Profile.class.getClassLoader().getResource(fileName).getFile(); System.out.println("propertiesPath:" + filePath); Properties props = new Properties(); BufferedReader br = null; BufferedWriter bw = null; try { // 从输入流中读取属性列表(键和元素对) br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath))); props.load(br); br.close(); // 写入属性文件 bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath))); // 清空旧的文件 // props.clear(); for (String key : keyValueMap.keySet()) props.setProperty(key, keyValueMap.get(key)); props.store(bw, "改变数据"); System.out.println(props.getProperty("url")); bw.close(); } catch (IOException e) { e.printStackTrace(); System.err.println("Visit " + filePath + " for updating " + "" + " value error"); } finally { try { br.close(); bw.close(); } catch (IOException e) { e.printStackTrace(); } } }
修改前:
运行测试结果即修改后:
public static void main(String[] args) { Profile.updateProperties("jdbc.properties", new HashMap<String, String>() { { put("initialSize", "6"); put("test", "修改文件属性"); } }); }