小伙伴啊,小伙伴,你真是懒得动手!
代码如下:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import com.intector.fcy.csources.exception.EType;
import com.intector.fcy.csources.exception.IntecException;
/**
* @ClassName: PropUtils
* @Description: TODO(属性文件工具类)
* @author intector_FHQ
* @date 2017年3月10日 下午1:39:24
*
*/
public class PropUtils {
private final ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
/**
* 文件前缀
*/
private String prefixNmae = "props";
protected boolean isScanning;
private Long scanningS;
private Long initialDelay = 10L;
protected int fileCount;
protected String txpath;
protected Map<String, PropMegs> props;
public Long getInitialDelay() {
return initialDelay;
}
public void setInitialDelay(Long initialDelay) {
this.initialDelay = initialDelay;
}
public Long getScanningS() {
return scanningS;
}
public void setScanningS(Long scanningS) {
this.scanningS = scanningS;
}
public String getPrefixNmae() {
return prefixNmae;
}
public void setPrefixNmae(String prefixNmae) {
this.prefixNmae = prefixNmae;
}
/**
* @Title: getPropValueByKey @Description: TODO(获取属性文件中属性的值) @param @param
* propName @param @param key @param @return 设定文件 @return String
* 返回类型 @throws
*/
public String getPropValueByKey(String propName, String key) {
if(this.props==null||this.props.size()==0){
return null;
}
if(this.props.get(propName)==null){
return null;
}
return this.props.get(propName).getProperties().getProperty(key);
}
/**
* <p>
* 构造器:
* </p>
* <p>
* 扫描指定地方的文件,并加载:
* </p>
*
* @throws Exception
*/
public PropUtils(boolean isScanning) {
// TODO Auto-generated constructor stub
try {
this.txpath = java.net.URLDecoder
.decode(ClassLoader.getSystemClassLoader().getResource(this.prefixNmae).getPath(), "utf-8");
this.isScanning = isScanning;
this.getProps();
this.fileCount = this.props.size();
if (isScanning) {
this.scanningS = 5L;
this.scanningProps(this);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public PropUtils() {
try {
this.txpath = java.net.URLDecoder
.decode(ClassLoader.getSystemClassLoader().getResource(this.prefixNmae).getPath(), "utf-8");
this.txpath = java.net.URLDecoder.decode(this.txpath, "utf-8");
this.getProps();
this.fileCount = this.props.size();
this.isScanning = false;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
public PropUtils(boolean isScanning, Long scanningS) {
try {
this.txpath = java.net.URLDecoder
.decode(ClassLoader.getSystemClassLoader().getResource(this.prefixNmae).getPath(), "utf-8");
this.isScanning = isScanning;
this.getProps();
this.fileCount = this.props.size();
if (isScanning) {
// 开始扫描
this.scanningS = scanningS;
this.scanningProps(this);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* <p>
* 构造器:
* </p>
* <p>
* Description:
* </p>
*
* @param isScanning
* @param scanningS
* @param initialDelay
* @throws Exception
*/
public PropUtils(boolean isScanning, Long initialDelay, Long scanningS) {
try {
this.txpath = java.net.URLDecoder
.decode(ClassLoader.getSystemClassLoader().getResource(this.prefixNmae).getPath(), "utf-8");
this.getProps();
this.fileCount = this.props.size();
this.isScanning = isScanning;
this.initialDelay = initialDelay;
if (isScanning) {
// 开始扫描
this.scanningS = scanningS;
this.scanningProps(this);
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
/**
* @throws Exception
* @Title: getPropMegs @Description: TODO(读取属性文件) @param @return
* 设定文件 @return List<propMegs> 返回类型 @throws
*/
private void getProps() throws Exception {
this.props = new HashMap<String, PropMegs>();
File file = new File(this.txpath);
if (file.exists()) {
this.Analyticaldata(file);
} else {
throw new IntecException("文件目录不存在!", EType.SYS);
}
}
private void Analyticaldata(File file) throws IOException {
// TODO Auto-generated method stub
File[] files = file.listFiles();
for (File f : files) {
if (f.isFile()) {
if ("properties"
.equals(f.getName().substring(f.getName().lastIndexOf(".") + 1, f.getName().length()))) {
Properties prop = new Properties();
InputStream in = new FileInputStream(f);
prop.load(in);
PropMegs megs = new PropMegs(f.getName(),f.lastModified() + "", prop);
megs.setFilePath(f.getPath());
this.props.put(f.getName().substring(0, f.getName().lastIndexOf(".")), megs);
in.close();
}
} else {
this.Analyticaldata(f);
}
}
}
/**
* @param propUtils
* @Title: scanningProps @Description: TODO(定时扫描) @param @throws
* Exception 设定文件 @return void 返回类型 @throws
*/
public void scanningProps(final PropUtils propUtils) throws Exception {
// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
service.scheduleAtFixedRate(new Runnable() {
public void run() {
// task to run goes here
System.out.println("Intector>Proputils start scanning path[" + propUtils.txpath + "] time "
+ new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date()));
try {
propUtils.scanningDatas();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Intector scanning stop because this catch " + e.getMessage() + " time is "
+ new SimpleDateFormat("yyyy-MM-DD HH:mm:ss").format(new Date()));
service.shutdown();
}
}
}, this.initialDelay, this.scanningS, TimeUnit.MINUTES);
}
/**
* 监听文件 @Title: scanningDatas @Description:
* TODO(这里用一句话描述这个方法的作用) @param @throws Exception 设定文件 @return void
* 返回类型 @throws
*/
private void scanningDatas() throws Exception {
File file = new File(this.txpath);
if (file.exists()) {
if (file.listFiles().length == 0) {
throw new IntecException("文件目录下不存在任何文件!", EType.SYS);
} else {
this.Analyticaldatas(file);
Iterator<String> iterator = this.props.keySet().iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
PropMegs pm = this.props.get(key);
File fi = new File(pm.getFilePath());
if (!fi.exists()) {
iterator.remove(); // 添加该行代码
this.props.remove(key);
}
}
this.fileCount = this.props.size();
}
} else {
throw new IntecException("文件目录不存在!", EType.SYS);
}
}
private void Analyticaldatas(File file) throws Exception, IOException {
// TODO Auto-generated method stub
File[] files = file.listFiles();
for (File f : files) {
if (f.isFile()) {
if ("properties"
.equals(f.getName().substring(f.getName().lastIndexOf(".") + 1, f.getName().length()))) {
PropMegs pm = this.props.get(f.getName());
if (pm == null || !pm.getFileTime().equals(f.lastModified() + "")) {
Properties prop = new Properties();
InputStream in = new FileInputStream(f);
prop.load(in);
PropMegs megs = new PropMegs(f.getName(),f.lastModified() + "", prop);
megs.setFilePath(f.getPath());
this.props.put(f.getName().substring(0, f.getName().lastIndexOf(".")), megs);
in.close();
}
}
} else {
this.Analyticaldatas(f);
}
}
}
/**
*
* @Title: destory @Description: TODO(销毁时触发) @param 设定文件 @return void
* 返回类型 @throws
*/
protected void destory() {
service.shutdown();
this.props=null;
this.fileCount=0;
this.isScanning=false;
this.scanningS=0L;
this.initialDelay=0l;
this.txpath=null;
}
/**
* @ClassName: propMegs
* @Description: TODO(文件描述对象--内部对象)
* @author intector_FHQ
* @date 2017年3月10日 下午5:43:41
*/
public class PropMegs {
private String fileName;
private String fileTime;
private String filePath;
private Properties properties;
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFileTime() {
return fileTime;
}
public void setFileTime(String fileTime) {
this.fileTime = fileTime;
}
public PropMegs() {
super();
// TODO Auto-generated constructor stub
}
public PropMegs(String fileName, String fileTime, Properties properties) {
super();
this.fileName = fileName;
this.fileTime = fileTime;
this.properties = properties;
}
}
}
测试代码如下:
public class TProputils {
public static void main(String[] args) {
final PropUtils propUtils=new PropUtils(true);
System.out.println(propUtils.toString());
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(new Runnable() {
public void run() {
// task to run goes here
System.out.println(propUtils.getPropValueByKey("server", "dirver"));
}
}, 20, 1, TimeUnit.SECONDS);
}
}
spring 配置如下:
<!-- 引入属性配置文件 自定义属相文件加载类
3中构造方法 isScanning:是否开启自动扫描 默认false
scanningS: 扫描周期 默认5 单位分钟
initialDelay:延迟扫描时间 默认10 单位秒 -->
<bean id="propsBean" class="com.intector.fcy.csources.comutils.props.PropUtils" scope="singleton" destroy-method="destory"/>
<!--
<bean id="propsBean" class="com.intector.fcy.csources.comutils.props.PropUtils">
<constructor-arg name="isScanning" value="true" />
</bean>
<bean id="propsBean" class="com.intector.fcy.csources.comutils.props.PropUtils">
<constructor-arg name="isScanning" value="true" /> <constructor-arg name="scanningS" value="5" />
</bean>
<bean id="propsBean" class="com.intector.fcy.csources.comutils.props.PropUtils">
<constructor-arg name="isScanning" value="true" />
<constructor-arg name="scanningS" value="5" />
<constructor-arg name="initialDelay" value="10" />
</bean>
-->
工具类使用说明:
1.在项目根目录创建 props 文件夹 (名称可在工具类下修改)这里不支持构造注入;
2.工具类运行后自动加载 props 文件加下的所有 属性文件(包含嵌套目录下的所有属性文件),将属性文件的内容及文件信息保存到工具类的map集合中;
3.可配置是否定期自动扫描文件,若文件发生变化(修改,删除,新增),则及时更新工具类map内容;
该工具类可用于java web 项目中 频繁修改属性文件,就不用重启服务了。
web 中将
this.txpath = java.net.URLDecoder
.decode(ClassLoader.getSystemClassLoader().getResource(this.prefixNmae).getPath(), "utf-8");
改为
this.txpath = java.net.URLDecoder.decode(this.getClass().getClassLoader().getResource(this.prefixNmae).getPath(), "utf-8");