Properties
在Java中属性操作类是一个很重要的类,而要想明白属性操作类的作用,就必须先要清楚什么是属性文件,在属性文件中含有多个属性,每个属性就是直接用字符串表示出来的"key=value 键/值对", 而如果要想轻松操作这些属性需要使用Properties类完成.
1.简单认识Properties
- public class Properties extends Hashtable<Object,Object>
- 复制代码
编号 | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public Properties() | 构造 | 创建一个无默认值的空属性类 |
2 | public Properties(Properties props) | 构造 | 创建一个带有指定默认值的空属性类 |
3 | public String getProperty(String key) | 普通方法 | 根据属性的key取得属性的value,如果没有,将放回null |
4 | public String getProperty(String key, String defaultValue) | 普通方法 | 根据属性的key取得属性的value,如果没有,将返回defaultValue |
5 | public Object setProperty(String key, String value) | 普通方法 | 设置属性 |
6 | public void list(PrintStream out) | 普通方法 | 属性打印 |
7 | public void load(InputStream inStream) | 普通方法 | 将输入流中取出全部的属性内容 |
8 | public void loadFromXML(InputStream in) | 普通方法 | 从XML文件格式中读取内容 |
9 | public void store(OutputStream out, String comments) | 普通方法 | 将属性内容通过输出流输出,同时声明属性的注释内容 |
10 | public void storeToXML(OutputStream os, String comment) | 普通方法 | 以XML文件格式输出属性,默认编码 |
11 | public void storeToXML(OutputStream os, String comment, String encoding) | 普通方法 | 以XML文件格式输出属性,用户指定默认编码 |
实际开发中我们使用Properties的功能类似于存储的数据为Map<String,String>都是字符串的形式
2.Properties的操作实例
示例1:设置和取得属性
主要使用setProperty()和getProperty()方法设置和获取属性,存储的数据类型都是String
- package com.shxt.demo06;
-
- import java.util.Properties;
-
- public class Demo01 {
- public static void main(String[] args) {
- Properties props = new Properties(); //创建Properties对象
- //设置属性
- props.setProperty("title","胖先森博客");
- props.setProperty("version","v1.0");
- props.setProperty("db","MySQL 5.7");
-
- //获取属性
- System.out.println("1.title属性存在:"+props.getProperty("title"));
- System.out.println("2.name属性不存在:"+props.getProperty("name"));
- System.out.println("3.name属性不存在,显示默认值:"+props.getProperty("name","胖先森"));
-
- }
- }
- /*
- 运行结果:
- 1.title属性存在:胖先森博客
- 2.name属性不存在:null
- 3.name属性不存在,显示默认值:胖先森
- */
- 复制代码
示例2:保存属性到普通的属性文件
- package com.shxt.demo06;
-
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.Properties;
-
- public class Demo02 {
- public static void main(String[] args) {
- Properties props = new Properties(); //创建Properties对象
- //设置属性
- props.setProperty("title","胖先森博客");
- props.setProperty("version","v1.0");
- props.setProperty("db","MySQL 5.7");
-
- //设置属性文件的保存路径,使用绝对路径
- //关于文件的操作,我们在后面J2EE文件上传的时候会再次说明
- File file = new File("D:/sys.properties");
- try {
- props.store(new FileOutputStream(file),"system config");
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- 复制代码
运行结果:
说明:如果是中文会使用Unicode进行转换
示例3:从属性文件中读取内容
- package com.shxt.demo06;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.util.Properties;
-
- public class Demo03 {
- public static void main(String[] args) {
- Properties props = new Properties(); //创建Properties对象
-
- //跟磁盘中的文件建立联系
- File file = new File("D:/sys.properties");
- try {
- //读取属性文件
- props.load(new FileInputStream(file));
- //获取属性
- System.out.println("getProperty():"+props.getProperty("title"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- /*
- 运行结果:
- getProperty():胖先森博客
- */
- 复制代码
下面的简单了解就好
示例4:将属性文件保存到XML文件中
- package com.shxt.demo06;
-
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.util.Properties;
-
- public class Demo04 {
- public static void main(String[] args) {
- Properties props = new Properties(); //创建Properties对象
- //设置属性
- props.setProperty("title","胖先森博客");
- props.setProperty("version","v1.0");
- props.setProperty("db","MySQL 5.7");
-
- //跟磁盘中的文件建立联系,文件的后缀名必须为.xml
- File file = new File("D:/sys.xml");
- try {
- props.storeToXML(new FileOutputStream(file),"system config");
-
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- 复制代码
运行结果:
示例5:从XML文件中读取属性
- package com.shxt.demo06;
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.util.Properties;
-
- public class Demo05 {
- public static void main(String[] args) {
- Properties props = new Properties(); //创建Properties对象
-
- //跟磁盘中的文件建立联系
- File file = new File("D:/sys.xml");
- try {
- //读取XML文件
- props.loadFromXML(new FileInputStream(file));
- //获取属性
- System.out.println("getProperty():"+props.getProperty("title"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- /*
- 运行结果:
- getProperty():胖先森博客
- */
- 复制代码
3.认识Properties文件
- properties文件是一个文本文件
- properties文件的语法有两种,一种是注释,一种属性配置。
- 注释:前面加上#号
- 属性配置:以"键=值"的方式书写一个属性的配置信息,都是字符串。
- properties文件的一个属性配置信息值可以换行,但键不可以换行。值换行用“\”表示。
- properties的属性配置键值前后的空格在解析时候会被忽略。
- properties文件可以只有键而没有值。也可以仅有键和等号而没有值,但无论如何一个属性配置不能没有键。
不推荐的写法
- #正确的properties配置文件
- aaa=wu\
- kong
- b
- bb = bajie
- 复制代码
推荐的写法
- #格式良好的properties文件
- aaa=wukong
- bbb=bajie
- 复制代码
4.读取Properties文件的方法
(1) 使用java.util.Properties类的load()方法
你需要提供一共绝对路径读取数据,"D:/sys.properties"类似的路径,我个人不怎么推荐使用
- package com.shxt.demo06;
-
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.util.Properties;
-
- public class Demo06 {
- public static void main(String[] args) {
- Properties props = new Properties();
- try {
- props.load(new FileInputStream("D:/sys.properties"));
- //获取属性
- System.out.println("title属性的值:"+props.getProperty("title"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- 复制代码
(2) 使用java.util.ResourceBunld类的getBundle()方法[掌握]
通过ResourceBundle.getBundle()
静态方法来获取(ResourceBundle是一个抽象类),这种方式来获取properties属性文件不需要加.properties后缀名,只需要文件名即可.
- 属性文件在src的根目录下
-
- package com.shxt.demo06;
-
- import java.util.ResourceBundle;
-
- public class Demo07 {
- public static void main(String[] args) {
- ResourceBundle resouce = ResourceBundle.getBundle("sys");
- //获取属性
- System.out.println("title属性的值:"+resouce.getString("title"));
- }
- }
- 复制代码
- 属性文件在包com.shxt.demo06
- package com.shxt.demo06;
-
- import java.util.ResourceBundle;
-
- public class Demo08 {
- public static void main(String[] args) {
- //sys为属性文件名,放在包com.shxt.demo06下,如果是放在src下,直接用sys即可
- ResourceBundle resouce = ResourceBundle.getBundle("com/shxt/demo06/sys");
- //获取属性
- System.out.println("title属性的值:"+resouce.getString("title"));
- }
- }
- 复制代码
(3) 使用PropertyResourceBundle
- package com.shxt.demo06;
-
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.util.PropertyResourceBundle;
- import java.util.ResourceBundle;
-
- public class Demo09 {
- public static void main(String[] args) {
- try {
- ResourceBundle resource = new PropertyResourceBundle(new FileInputStream("D:/sys.properties"));
- //获取属性
- System.out.println("title属性的值:"+resource.getString("title"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- 复制代码
(4) 使用class变量的getResourceAsStream()方法
- package com.shxt.demo06;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
-
- public class Demo11 {
- public static void main(String[] args) {
- // /config/sys.properties 从src的根目录开始查找,记住这个"/"
- // 如果没有这个斜线,那么会报空指针异常
- InputStream in = Demo11.class.getResourceAsStream("/config/sys.properties");
- Properties props = new Properties();
- try {
- props.load(in);
- //获取属性
- System.out.println("title属性的值:"+props.getProperty("db"));
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- }
-
- 复制代码
(5) 使用class.getClassLoader()所得到的java.lang.ClassLoader的getResourceAsStream()方法
- package com.shxt.demo06;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
-
- public class Demo12 {
- public static void main(String[] args) {
-
- InputStream in = Demo12.class.getClassLoader().getResourceAsStream("config/sys.properties");
- Properties props = new Properties();
- try {
- props.load(in);
- //获取属性
- System.out.println("title属性的值:"+props.getProperty("db"));
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
- }
-
- 复制代码
感觉上就是少了一个斜线而已
(6) 使用java.lang.ClassLoader类的getSystemResourceAsStream()静态方法[推荐]
- package com.shxt.demo06;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.util.Properties;
-
- public class Demo13 {
- public static void main(String[] args) {
-
- InputStream in = ClassLoader.getSystemResourceAsStream("config/sys.properties");
- Properties props = new Properties();
- try {
- props.load(in);
- //获取属性
- System.out.println("title属性的值:"+props.getProperty("db"));
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- 复制代码
7.补充:Servlet中可以使用javax.servlet.ServletContext的getResourceAsStream()方法
- InputStream in = context.getResourceAsStream(path);
- Properties p = new Properties();
- p.load(in);
- 复制代码
5.技术穿越
这里分享一个简单的封装的工具类
- package com.pangsir.helper.properties;
-
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import java.io.*;
- import java.util.Properties;
-
-
- /**
- * 加载属性文件
- *
- * @author 刘文铭
- * @see com.pangsir.helper.properties.PropertiesConfigHelper
- * @since 1.0
- */
- public class PropertiesConfigHelper {
- private PropertiesConfigHelper(){}
-
- //使用日志输出
- private final static Logger logger = LoggerFactory.getLogger(PropertiesConfigHelper.class);
- //设置后缀名
- private final static String EXT = ".properties";
- //实例化Properties对象
- private static Properties configProperties = null;
-
- /**
- * 加载properties文件
- *
- * @param filepaths properties文件路径
- */
- public static void load(String... filepaths) {
- logger.debug("开始读取properties文件 开始时间" + System.currentTimeMillis());
- if(configProperties==null){
- configProperties = new Properties();
- }
- //配置文件路径
- String configFilePath;
- InputStream inputStream = null;
- //遍历filepathke数组
- for (int i = 0; i < filepaths.length; i++) {
- configFilePath = filepaths[i];
- //读取属性文件后缀名为.properties
- try {
- if (configFilePath.toLowerCase().endsWith(EXT)) {
- inputStream = PropertiesConfigHelper.class.getClassLoader().getResourceAsStream(configFilePath);
- configProperties.load(inputStream);
- } else {
- throw new RuntimeException("无法读取该文件: " + configFilePath);
- }
- logger.debug("文件 \"" + configFilePath + "\" 读取 成功! 时间为:" + System.currentTimeMillis());
- } catch (Exception e) {
- logger.debug("文件 \"" + configFilePath + "\" 读取 失败, 失败异常信息:\\n" + e.getMessage());
- throw new RuntimeException("文件 \"" + configFilePath + "\" 加载失败", e);
- } finally {
- if (inputStream != null) {
- try {
- inputStream.close();
- } catch (IOException e) {
- logger.debug("所有配置文件读取完毕,当关闭文件FileInputStream时,异常信息 :\\n" + e.getMessage());
- }
- }
- }
-
- }
-
- }
-
- /**
- * 获取 int 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 对应的配置属性value,如果配置属性的value不为short类型或不存在对应的配置属性,则返回 defaultValue
- */
- public static Short getShortValue(String key, Short defaultValue) {
- try {
- return getShortValue(key);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- /**
- * 获取 short 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static Short getShortValue(String key) {
- return Short.parseShort(configProperties.getProperty(key));
- }
-
- /**
- * 获取 int 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 对应的配置属性value,如果配置属性的value不为int类型或不存在对应的配置属性,则返回 defaultValue
- */
- public static int getIntegerValue(String key, Integer defaultValue) {
- try {
- return getIntegerValue(key);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- /**
- * 获取 int 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static Integer getIntegerValue(String key) {
- return Integer.parseInt(configProperties.getProperty(key));
- }
-
-
- /**
- * 获取 float 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 对应的配置属性value,如果配置属性的value不为float类型或不存在对应的配置属性,则返回 defaultValue
- */
- public static Float getFloatValue(String key, float defaultValue) {
- try {
- return getFloatValue(key);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- /**
- * 获取 float 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static Float getFloatValue(String key) {
- return Float.parseFloat(configProperties.getProperty(key));
- }
-
- /**
- * 获取 double 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 对应的配置属性value,如果配置属性的value不为double类型或不存在对应的配置属性,则返回 defaultValue
- */
- public static Double getDoubleValue(String key, double defaultValue) {
- try {
- return getDoubleValue(key);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
- /**
- * 获取 Double 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static Double getDoubleValue(String key) {
- return Double.parseDouble(configProperties.getProperty(key));
- }
-
-
-
- /**
- * 获取 long 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 对应的配置属性value,如果配置属性的value不为long类型或不存在对应的配置属性,则返回 defaultValue
- */
- public static Long getLongValue(String key, long defaultValue) {
- try {
- return getLongValue(key);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
- /**
- * 获取 Long 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static Long getLongValue(String key) {
- return Long.parseLong(configProperties.getProperty(key));
- }
-
-
-
- /**
- * 获取 String 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 对应的配置属性value,如果配置属性的value为""或不存在对应的配置属性,则返回 defaultValue
- */
- public static String getStringValue(String key, String defaultValue) {
- String value = configProperties.getProperty(key);
- return (value == null) ? defaultValue : getStringValue(key);
- }
- /**
- * 获取 String 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static String getStringValue(String key) {
- return configProperties.getProperty(key);
- }
-
- /**
- * 获取 boolean 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @param defaultValue 默认值
- * @return 如果在配置文件中没有定义此属性,则返回 defaultValue;
- * 如果 value 为y、on、yes 、true 或非 0 数值(均不区分大小写) 则返回 true, 否则返回 false
- */
- public static boolean getBooleanValue(String key, Boolean defaultValue) {
- String value = configProperties.getProperty(key);
- return (value == null) ? defaultValue : getBooleanValue(key);
- }
- /**
- * 获取 boolean 类型的配置属性的value
- *
- * @param key 配置属性的key
- * @return 对应的配置属性value
- */
- public static Boolean getBooleanValue(String key) {
- String value = configProperties.getProperty(key);
- return ("y".equalsIgnoreCase(value)) || ("on".equalsIgnoreCase(value)) || ("yes".equalsIgnoreCase(value))
- || ("true".equalsIgnoreCase(value)) || (getIntegerValue(key, 0) != 0);
- }
- /**
- * 加载properties文件
- *
- * @param filepath properties文件路径
- */
- public static void write(String key, String value,String filepath){
- if(configProperties==null){
- configProperties = new Properties();
- }
-
- OutputStream outputStream = null;
- try{
- String base = PropertiesConfigHelper.class.getResource("/"+filepath).getPath();
- java.net.URL url = PropertiesConfigHelper.class.getResource("/"+filepath);
- File file = new File(url.toURI());
- //判断文件是否存在
- if(!file.exists()){
- file.createNewFile();
- }
-
- load(filepath);//加载文件
-
- outputStream = new FileOutputStream(file);
-
- configProperties.setProperty(key,value);
-
- configProperties.store(outputStream,"");
-
-
- }catch (Exception e){
- throw new RuntimeException("文件 \"" + filepath + "\" 加载失败", e);
- }finally {
- if (outputStream != null) {
- try {
- outputStream.close();
- } catch (IOException e) {
- logger.debug("所有配置文件修改完毕,FileOutputStream异常信息 :\\n" + e.getMessage());
- }
- }
- }
-
- }
- }
-
- 复制代码
重点:将properties文件的配置设置为整个Web应用的全局变量实现方法,学到J2EE阶段再使用下面的方式
WEB域的简单说明:
Web应用中的变量存放在不同的jsp对象中,会有不一样的作用域,四种不同的作用域排序是 pageContext < request < session < application;
- pageContext:页面域,仅当前页面有效,离开页面后,不论重定向还是转向(即无论是redirect还是forward),pageContext的属性值都失效;
- request:请求域,在一次请求中有效,如果用forward转向,则下一次请求还可以保留上一次request中的属性值,而redirect重定向跳转到另一个页面则会使上一次request中的属性值失效;
- session:会话域,在一次会话过程中(从浏览器打开到浏览器关闭这个过程),session对象的属性值都保持有效,在这次会话过程,session中的值可以在任何页面获取;
- application:应用域,只要应用不关闭,该对象中的属性值一直有效,并且为所有会话所共享
思路说明:
利用ServletContextListener监听器,一旦应用加载,就将properties的值存储到application当中.
现在需要在所有的jsp中都能通过EL表达式读取到properties中的属性,并且是针对所有的会话,故这里利用application作用域,那么什么时候将properties中的属性存储到application呢?因为是将properties的属性值作为全局的变量以方便任何一次EL的获取,所以在web应用加载的时候就将值存储到application当中.
这里就要利用ServletContextListener:
- ServletContextListener是Servlet API 中的一个接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。
- 当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent 事件,该事件由ServletContextListener 来处理。
具体步骤:
- (1) 新建一个类PropertyListenter实现 ServletContextListener接口的contextInitialized方法;
- (2) 读取properties配置文件,转存到Map当中;
- (3) 使用ServletContext对象将Map存储到application作用域中;
- /**
- * 设值全局变量
- */
- public class PropertyListenter implements ServletContextListener {
- private static final Logger logger = (Logger) LoggerFactory.getLogger(PropertyListenter.class);
- @Override
- public void contextDestroyed(ServletContextEvent context) {}
- @Override
- public void contextInitialized(ServletContextEvent sce) {
- /**
- * 读取properties文件
- */
- Properties properties = new Properties();
-
- InputStream in = null;
- try {
- //通过类加载器进行获取properties文件流
- in = PropertiesUtil.class.getClassLoader().getResourceAsStream("sys.properties");
- properties.load(in);
-
- } catch (FileNotFoundException e) {
- logger.error("未找到properties文件");
- } catch (IOException e) {
- logger.error("发生IOException异常");
- } finally {
- try {
- if(null != in) {
- in.close();
- }
- } catch (IOException e) {
- logger.error("properties文件流关闭出现异常");
- }
- }
-
- /**
- * 将properties文件转存到map.关键步骤
- */
- Map<String, String> pros = new HashMap<String,String>((Map)properties);
-
- /**
- * 将Map通过ServletContext存储到全局作用域中
- */
- ServletContext sct=sce.getServletContext();
-
- sct.setAttribute("pros", pros);
-
- }
-
-
- }
- 复制代码