描述:
java程序在编写的时候,有些参数由于不确定,或者说在开发中,测试中,生产上的数据值都是不同的,比如ip地址和端口,开发中url的是自己写的测试url,测试和生产环境中要变更url地址,如果这些信息写在java文件中,那就会非常难以修改并且不安全,因为到后期测试中,是没有java源码的,都是编译后的class文件,你要修改系统的参数,只能修改.java文件再编译成class文件再替换到测试环境中,即麻烦又不安全,所以要有配置文件,把系统重要的常变的参数写在里面,在环境切换需要修改参数时就可以直接通过修改配置文件的数据来达到目的,这也是为什么一个程序必须要有配置文件的原因。
java写配置文件要注意要对配置信息进行分类,大概分为:
系统固定参数:这一类的数据是在系统配置类里写死的,不会变的,如配置文件的路径,系统日志名称,系统编码等
系统配置参数:这类参数写在配置文件中,如system.properties,里面保存的是系统的重要参数,如系统名称,系统唯一编码,唯一秘钥,对接服务器地址等
模块配置参数:这类参数是系统不同模块需要的参数,也是写在配置文件中,保存的是模块需要的参数,如模块名称,模块文件路径,或者其他信息
步骤:
一:创建系统日志,为啥要有日志就不说了,可以参考我的另一篇博客:
public class SysConfig {
private static Logger logger = LoggerUtil.getLogger(SysConfig.class);
}
二:编写配置文件system.properties,放到src目录下就可以了
system.zhfdc.logname=ZHFDC
system.zhfdc.bank.banknumber=EVERCNBJ016
system.zhfdc.bank.bankname=\u67D0\u67D0\u94F6\u884C
system.zhfdc.bank.encryptkey=3X4XoBbLU7
system.zhfdc.bank.serverurl=http://localhost:18080/ZcnjbServer/services/BankService?wsdl
module.zhfdc.name=\u6A21\u5757\u540D\u79F0
module.zhfdc.filepath=\u6A21\u5757\u6587\u4EF6\u8DEF\u5F84
module.zhfdc.othermsg=\u5176\u4ED6\u4FE1\u606F
三:配置系统固定参数:
public class SysConfig {
private static Logger logger = LoggerUtil.getLogger(SysConfig.class);
/*-----------------系统固定参数--------------------*/
private static Properties props = null;
private static final String LOCAL_PATH = SysConfig.class.getResource("/").getFile();//系统路径
public static String SYSPROPFILE = LOCAL_PATH + "system.properties"; //系统配置文件位置
public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
public static final Charset SYSDEF_CHARSET = Charset.defaultCharset();
public static final Charset GBK_CHARSET = Charset.forName("GBK");
public static final Charset GB2312_CHARSET = Charset.forName("GB2312");
}
四:配置系统参数:
public class SysConfig {
private static Logger logger = LoggerUtil.getLogger(SysConfig.class);
/*-----------------系统固定参数--------------------*/
private static Properties props = null;
private static final String LOCAL_PATH = SysConfig.class.getResource("/").getFile();//系统路径
public static String SYSPROPFILE = LOCAL_PATH + "system.properties"; //系统配置文件位置
public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
public static final Charset SYSDEF_CHARSET = Charset.defaultCharset();
public static final Charset GBK_CHARSET = Charset.forName("GBK");
public static final Charset GB2312_CHARSET = Charset.forName("GB2312");
/*-----------------系统配置参数--------------------*/
public static String LOGNAME = "ZHFDC"; //系统配置固定参数默认值,如果配置文件没有该值则为默认值
public static String BANKNUMBER = "BANKNUMBER";//银行统一编码
public static String BANKNAME = "BANKNAME";//银行名称
public static String ENCRYPTKEY = "encryptkey";//银行签名秘钥
public static String SERVICE_WSDLURL = null;//对接服务器地址 "http://localhost:18080/ZcnjbServer/services/BankService?wsdl"
//初始化配置参数
static {
initParams();
}
/**
* 加载配置文件
*/
private static void initParams() {
props = new Properties();
Reader reader = null;
try {
logger.info("——————————————————————————————【系统参数配置信息】——————————————————————————————");
logger.info("SYSPROPFILE:"+SYSPROPFILE);
reader = new InputStreamReader(new FileInputStream(SYSPROPFILE), SYSDEF_CHARSET);
props.load(reader);
LOGNAME = props.getProperty("system.zhfdc.logname", "ZHFDC");//获取配置文件值,如果获取失败则赋予值“ZHFDC”
BANKNUMBER = props.getProperty("system.zhfdc.bank.banknumber", "BANKNUMBER");
BANKNAME = props.getProperty("system.zhfdc.bank.bankname", "BANKNAME");
ENCRYPTKEY = props.getProperty("system.zhfdc.bank.encryptkey", "encryptkey");
SERVICE_WSDLURL = props.getProperty("system.zhfdc.bank.serverurl", "http://localhost:18080/ZcnjbServer/services/BankService?wsdl");
//日志打印配置信息
logger.info("LOGNAME:"+LOGNAME);
logger.info("BANKNUMBER:"+BANKNUMBER);
logger.info("BANKNAME:"+BANKNAME);
logger.info("ENCRYPTKEY:"+ENCRYPTKEY);
logger.info("SERVICE_WSDLURL:"+SERVICE_WSDLURL);
// DZDZFILEPATH = new File(props.getProperty(
// "system.zcnjb.dzdzd.path", LOCAL_PATH + "data/zcnjb/prod"))
// .getAbsolutePath();
} catch (Exception e) {
logger.info("系统参数配置异常,采用默认配置:" + e.getMessage(), e);
throw new RuntimeException("系统参数配置异常,采用默认配置:" + e.getMessage(), e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
}
logger.info("——————————————————————————————(系统配置结束)——————————————————————————————");
}
}
五:配置模块配置信息:
写一个获取配置参数的方法,在我这里,我获取模块配置信息的方式是根据配置文件的属性名来获取属性值。
/**获取配置信息
* @param key 属性名
* @param value 属性值
* @return
*/
private static String getPro(String key){
try {
return props.getProperty(key);
} catch (Exception e) {
logger.info("获取配置信息失败:"+e.getMessage());
return null;
}
}
/** 添加或修改配置信息
* @param key 属性名
* @param value 属性值
* @return
*/
private static Boolean updatePro(String key,String value){
// 文件输出流
try {
logger.info("获取添加或修改前的属性值:"+key+"=" + props.getProperty(key));
props.setProperty(key, value);
FileOutputStream fos = new FileOutputStream(SYSPROPFILE);
// 将Properties集合保存到流中
props.store(fos, "Update '" + key + "' value");
fos.close();// 关闭流
} catch (Exception e) {
logger.info("添加或修改配置信息失败:"+e.getMessage());
e.printStackTrace();
return false;
}
initParams();//更新完配置参数后重新加载
logger.info("获取添加或修改后的属性值:"+key+"=" + props.getProperty(key));
return true;
}
六:测试方法:
public static void main(String[] args) throws Exception {
System.out.println("获取系统配置信息");
System.out.println(SysConfig.LOGNAME);
System.out.println(SysConfig.BANKNAME);
System.out.println(SysConfig.BANKNUMBER);
System.out.println(SysConfig.ENCRYPTKEY);
System.out.println(SysConfig.SERVICE_WSDLURL+"\r\n");
System.out.println("获取模块配置信息");
System.out.println(SysConfig.getPro("module.zhfdc.name"));
System.out.println(SysConfig.getPro("module.zhfdc.filepath"));
System.out.println(SysConfig.getPro("module.zhfdc.othermsg"));
}
七:测试结果:
[2019-01-17 11:23:09,492] [INFO] [com.qut.util.SysConfig.initParams:44] - ——————————————————————————————【系统参数配置信息】——————————————————————————————
[2019-01-17 11:23:09,494] [INFO] [com.qut.util.SysConfig.initParams:45] - SYSPROPFILE:/E:/work/workspaces/poin/VedioManage/build/classes/system.properties
[2019-01-17 11:23:09,494] [INFO] [com.qut.util.SysConfig.initParams:55] - LOGNAME:ZHFDC
[2019-01-17 11:23:09,495] [INFO] [com.qut.util.SysConfig.initParams:56] - BANKNUMBER:EVERCNBJ016
[2019-01-17 11:23:09,495] [INFO] [com.qut.util.SysConfig.initParams:57] - BANKNAME:某某银行
[2019-01-17 11:23:09,495] [INFO] [com.qut.util.SysConfig.initParams:58] - ENCRYPTKEY:3X4XoBbLU7
[2019-01-17 11:23:09,495] [INFO] [com.qut.util.SysConfig.initParams:59] - SERVICE_WSDLURL:http://localhost:18080/ZcnjbServer/services/BankService?wsdl
[2019-01-17 11:23:09,495] [INFO] [com.qut.util.SysConfig.initParams:74] - ——————————————————————————————(系统配置结束)——————————————————————————————
获取系统配置信息
ZHFDC
某某银行
EVERCNBJ016
3X4XoBbLU7
http://localhost:18080/ZcnjbServer/services/BankService?wsdl
获取模块配置信息
模块名称
模块文件路径
其他信息
其实一共就两个文件,一个是system.properties,一个是SysConfig.java
完整的SysConfig.java类
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;
import java.util.Properties;
import org.apache.log4j.Logger;
public class SysConfig {
private static Logger logger = LoggerUtil.getLogger(SysConfig.class);
/*-----------------系统固定参数--------------------*/
private static Properties props = null;
private static final String LOCAL_PATH = SysConfig.class.getResource("/").getFile();//系统路径
public static String SYSPROPFILE = LOCAL_PATH + "system.properties"; //系统配置文件位置
public static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
public static final Charset SYSDEF_CHARSET = Charset.defaultCharset();
public static final Charset GBK_CHARSET = Charset.forName("GBK");
public static final Charset GB2312_CHARSET = Charset.forName("GB2312");
/*-----------------系统配置参数--------------------*/
public static String LOGNAME = "ZHFDC"; //系统配置固定参数默认值,如果配置文件没有该值则为默认值
public static String BANKNUMBER = "BANKNUMBER";//银行统一编码
public static String BANKNAME = "BANKNAME";//银行名称
public static String ENCRYPTKEY = "encryptkey";//银行签名秘钥
public static String SERVICE_WSDLURL = null;//对接服务器地址 "http://localhost:18080/ZcnjbServer/services/BankService?wsdl"
//初始化配置参数
static {
initParams();
}
/**
* 加载配置文件
*/
private static void initParams() {
props = new Properties();
Reader reader = null;
try {
logger.info("——————————————————————————————【系统参数配置信息】——————————————————————————————");
logger.info("SYSPROPFILE:"+SYSPROPFILE);
reader = new InputStreamReader(new FileInputStream(SYSPROPFILE), SYSDEF_CHARSET);
props.load(reader);
LOGNAME = props.getProperty("system.zhfdc.logname", "ZHFDC");//获取配置文件值,如果获取失败则赋予值“ZHFDC”
BANKNUMBER = props.getProperty("system.zhfdc.bank.banknumber", "BANKNUMBER");
BANKNAME = props.getProperty("system.zhfdc.bank.bankname", "BANKNAME");
ENCRYPTKEY = props.getProperty("system.zhfdc.bank.encryptkey", "encryptkey");
SERVICE_WSDLURL = props.getProperty("system.zhfdc.bank.serverurl", "http://localhost:18080/ZcnjbServer/services/BankService?wsdl");
//日志打印配置信息
logger.info("LOGNAME:"+LOGNAME);
logger.info("BANKNUMBER:"+BANKNUMBER);
logger.info("BANKNAME:"+BANKNAME);
logger.info("ENCRYPTKEY:"+ENCRYPTKEY);
logger.info("SERVICE_WSDLURL:"+SERVICE_WSDLURL);
// DZDZFILEPATH = new File(props.getProperty(
// "system.zcnjb.dzdzd.path", LOCAL_PATH + "data/zcnjb/prod"))
// .getAbsolutePath();
} catch (Exception e) {
logger.info("系统参数配置异常,采用默认配置:" + e.getMessage(), e);
throw new RuntimeException("系统参数配置异常,采用默认配置:" + e.getMessage(), e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
}
}
}
logger.info("——————————————————————————————(系统配置结束)——————————————————————————————");
}
/** 添加或修改配置信息
* @param key 属性名
* @param value 属性值
* @return
*/
private static Boolean updatePro(String key,String value){
// 文件输出流
try {
logger.info("获取添加或修改前的属性值:"+key+"=" + props.getProperty(key));
props.setProperty(key, value);
FileOutputStream fos = new FileOutputStream(SYSPROPFILE);
// 将Properties集合保存到流中
props.store(fos, "Update '" + key + "' value");
fos.close();// 关闭流
} catch (Exception e) {
logger.info("添加或修改配置信息失败:"+e.getMessage());
e.printStackTrace();
return false;
}
initParams();//更新完配置参数后重新加载
logger.info("获取添加或修改后的属性值:"+key+"=" + props.getProperty(key));
return true;
}
/**获取配置信息
* @param key 属性名
* @param value 属性值
* @return
*/
private static String getPro(String key){
try {
return props.getProperty(key);
} catch (Exception e) {
logger.info("获取配置信息失败:"+e.getMessage());
return null;
}
}
public static void main(String[] args) throws Exception {
System.out.println("获取系统配置信息");
System.out.println(SysConfig.LOGNAME);
System.out.println(SysConfig.BANKNAME);
System.out.println(SysConfig.BANKNUMBER);
System.out.println(SysConfig.ENCRYPTKEY);
System.out.println(SysConfig.SERVICE_WSDLURL+"\r\n");
System.out.println("获取模块配置信息");
System.out.println(SysConfig.getPro("module.zhfdc.name"));
System.out.println(SysConfig.getPro("module.zhfdc.filepath"));
System.out.println(SysConfig.getPro("module.zhfdc.othermsg"));
}
}
总结:
有的人会觉得第五步根据配置文件的属性名可以获取属性值,那前面那些就多余了,根本就不需要sysconfig.java这个系统配置类了,以后哪里需要用的时候直接props.getProperty(key)就可以了,其实不是不可以,但是这样做方便你一会,折磨你却无穷无尽,因为配置文件有时候不仅仅是改值,有时连属性名也会一起改,到时候你根本就记不起来项目哪个位置用过这个参数,你修改根本无从起手,只能一个一个看,简直爆炸,而你用一个静态类来加载参数,以后哪怕大改配置文件,你也只需要改这一个类就可以了,所有,这个类还真的不能省。
我这里的模块参数都是用SysConfig.getPro(key)获取的,有的人觉得模块参数可以写入系统配置参数中,但实际情况是这样会浪费系统资源,如下图(本博客配置文件架构),配置文件中有一百个配置信息,只有10个是系统参数,其他都是模块参数,如果所有参数都在类中写一个String去接收,相当于直接把系统配置文件增大了10倍,浪费类系统资源,而且系统参数是项目经常使用的,而且每个模块都是用得到的,而模块参数本来使用次数就少,而且模块之间的参数是相对独立的,A模块的参数B模块又用不到,相当于占着茅坑不拉屎,白白浪费资源,如果不是系统很大真的没有必要,所以配置文件是否在配置类中写一个参数去保存它,要参考这个参数的使用频繁度,重要性,使用广泛度。
如果对比较大的系统,可以采用下面两种架构建立配置文件:
情况一:
情况二:(除非是多人开发,每人开发一个模块,或者系统真的很大很大,否则不推荐)