我們在運維過程中,經常需要做一些配置,如果有一個工具可以幫你在線修改後臺配置文件
讀取配置文件內容,同步配置文件到所有機器,是跟我們帶來極大的便利性的。
如下爲我做這個工具的思路:
配置文件工具單獨在一個頁籤,頁面上顯示配置文件名稱,配置文件功能描述,配置文件內容
1、鼠標懸浮在配置文件內容時以懸浮的提示方式顯示文本內容
2、FileData字段帶超鏈接,點擊超鏈接時新開一個窗口,該窗口可以查看和修改文件內容
3、新窗口有兩個按鈕,保存和取消
4、點擊保存時將頁面的內容寫入到生產機對應的配置文件
5、當文件發生更改時,將文件同步copy到另外兩套服務器上
6、寫入文件時指定文件格式爲UTF-8,讀取配置文件內容時也用UTF-8
7、如果當前頁面編輯的是xml文件,則需要對特殊字符做轉譯
8、如果是properties文件,需要對空格的特殊處理
9、讀取配置文件寫一個熱加載的公共類,支持各種類型的文件
我會在系統上線前,運行代碼掃描指定目錄下我們可查看到的文件類型文件,把所有文件寫到files.txt文件
文件內容爲:文件名稱,功能描述,文件路徑
然後工具頁面從files.txt讀取這些內容,顯示到頁面上
用戶在點擊查看文件內容時,我們通過文件路徑去獲取文件內容單獨顯示
/* bcwti
*
* Copyright (c) 2010 Parametric Technology Corporation (PTC). All Rights Reserved.
*
* This software is the confidential and proprietary information of PTC
* and is subject to the terms of a software license agreement. You shall
* not disclose such confidential information and shall use it only in accordance
* with the terms of the license agreement.
*
* ecwti
*/
package ext.restlet;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.json.JSONException;
import wt.util.WTProperties;
/**
* This processor initializes and saves Promotion Requests with the attribute
* values entered in the Promotion Request wizard.
*
* <BR>
* <BR>
* <B>Supported API: </B>true <BR>
* <BR>
* <B>Extendable: </B>true
*
*/
public class FileSaveAndCopyTools {
private static List<String> fileFiter = Arrays.asList(".txt", ".properties", ".xls", ".xlsx", ".xml", ".xconf",
".vm");
public static void main(String[] args) throws JSONException, IOException {
String wthome = "D:\\ptc\\Windchill_10.0\\Windchill";
// (String) (WTProperties.getLocalProperties()).getProperty("wt.home", "") + File.separator;
// 測試初始化全量配置文件到files.txt文件
// String filesPath = wthome + File.separator +"codebase"+ File.separator+"ext";
// initFilesTxt(filesPath);
// 測試讀取指定路徑的文件內容
// String filesPath = wthome + File.separator +"codebase"+ File.separator+"wt.properties";
// System.out.println(readTxt(filesPath));
// 測試從files.txt讀取系統中全量的業務配置文件
// List<Map<String, String>> bussnessConfigFile = getPlmBussnessConfigFiles4FileTxt();
// System.out.println(bussnessConfigFile.toString());
// 根據文件路徑和頁面傳遞的內容修改文件
// filesPath = "D:\\ptc\\Windchill_10.0\\Windchill\\codebase\\files.txt";
// String fileTxt = "測試寫文件";
// boolean updateState = saveBussnessFile(filesPath, fileTxt);
// System.out.println(updateState);
// 頁面編輯配置文件的業務描述,點擊保存時將數據更新到files.txt文件
// String targetFilePath = "D:\\ptc\\Windchill_10.0\\Windchill\\codebase\\ext\\util\\mail\\footer.txt";
// boolean modifyState = saveFilesTxtContent(targetFilePath, "通用郵件配置文件模板");
// System.out.println("修改某個配置文件的描述,是否成功="+modifyState);
}
/**
*
* 使用文件通道的方式複製文件
* @param s
* 源文件
* @param t
* 複製到的新文件
*/
public static void fileChannelCopy(File sourceFile, File targetFile) {
FileInputStream fi = null;
FileOutputStream fo = null;
FileChannel in = null;
FileChannel out = null;
try {
fi = new FileInputStream(sourceFile);
fo = new FileOutputStream(targetFile);
in = fi.getChannel();// 得到對應的文件通道
out = fo.getChannel();// 得到對應的文件通道
in.transferTo(0, in.size(), out);// 連接兩個通道,並且從in通道讀取,然後寫入out通道
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fi.close();
in.close();
fo.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 初始化 wt_home/codebase/files.txt 文件 該文件包含codebase/ext目錄下的".txt", ".properties",
* ".xls", ".xlsx", ".xml", ".xconf",".vm" 類型配置文件名稱,文件路徑
*
* @param rootFilePath
*/
public static void initFilesTxt(String rootFilePath) {
BufferedOutputStream buff = null;
try {
// 配置文件所在目錄
File srcFolder = new File(rootFilePath);
// 遞歸功能獲取改目錄下所有想要類型的文件
List<Map<String, String>> configNameAndDesc = new ArrayList<Map<String, String>>();
configNameAndDesc = getAllFilesByPath(srcFolder, configNameAndDesc);
System.out.println(configNameAndDesc.size());
// 將文件名,路徑,用戶寫到一個配置文件全清單
String wthome =
"D:\\ptc\\Windchill_10.0\\Windchill";
// (String) (WTProperties.getLocalProperties()).getProperty("wt.home", "");
String fileName = wthome + File.separator + "codebase" + File.separator + "files.txt";
buff = new BufferedOutputStream(new FileOutputStream(new File(fileName)));
for (int i = 0; i < configNameAndDesc.size(); i++) {
Map<String, String> rowInfo = configNameAndDesc.get(i);
buff.write(rowInfo.get("fileName").toString().getBytes());
buff.write(" ".getBytes());
buff.write(rowInfo.get("fileDescription").toString().getBytes());
buff.write(" ".getBytes());
buff.write(rowInfo.get("filePath").toString().getBytes());
buff.write(" ".getBytes());
buff.write("\r\n".getBytes());
buff.write("\r\n".getBytes());
}
buff.flush();
buff.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (buff != null) {
try {
buff.close();
buff = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 根據文件的路徑獲取文件內容
*
* @param filePath
* @return
*/
public static String readTxt(String filePath) {
StringBuffer textStr = new StringBuffer();
try {
if (StringUtils.isBlank(filePath)) {
return "no data for the file.";
}
String wthome = (String) (WTProperties.getLocalProperties()).getProperty("wt.home", "");
filePath = filePath.replace("wt_home", wthome);
File file = new File(filePath);
if (file.isFile() && file.exists()) {
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
String lineText = null;
while ((lineText = br.readLine()) != null) {
textStr.append(lineText).append("\r\n");
}
br.close();
} else {
System.out.println("文件不存在!");
}
} catch (Exception e) {
System.out.println("文件讀取錯誤!");
}
return textStr.toString();
}
/**
* 根據配置文件路徑和前臺傳遞的內容保存文件
*
* @param filePath 文件路徑
* @param fileTxt 文件內容
* @return true/false
*/
public static boolean saveBussnessFile(String filePath, String fileTxt) {
if (StringUtils.isBlank(filePath)) {
return false;
}
BufferedOutputStream buff = null;
try {
String wthome = (String) (WTProperties.getLocalProperties()).getProperty("wt.home", "");
filePath = filePath.replace("wt_home", wthome);
File files4Txt = new File(filePath);
if (files4Txt.canRead() && files4Txt.canWrite()) {
buff = new BufferedOutputStream(new FileOutputStream(filePath));
buff.write(fileTxt.getBytes());
}
buff.flush();
buff.close();
/**
* 某個文件通過管理員工具修改後,後臺自動將該配置文件同步到生產所有的機器
* 1、獲取生產環境的IP集合
* 2、判斷當前用戶的IP是哪個
* 3、將當前IP已更新的文件與另外兩臺建立文件通道,copy文件
*/
InetAddress addr = InetAddress.getLocalHost();
String ipAddress = addr.getHostAddress();
//後續改成讀取配置文件,避免IP發生變化
String salveIp1 = "10.xx.xx.16";
String salveIp2 = "10.xx.xx.17";
String masterIp = "10.xx.xx.18";
List<String> plmIp = Arrays.asList(salveIp1,salveIp2,masterIp);
//排除需要copy的機器
if(plmIp.contains(ipAddress)) {
plmIp.remove(ipAddress);
}
//這裏雖然多寫了兩個變量,但是從代碼可讀性上來說是可以接受的
String currentPath = filePath.replaceAll("D:", ipAddress);
for (int i = 0; i < plmIp.size(); i++) {
String targetIp = plmIp.get(i);
String targetFilePath = currentPath.replaceAll(ipAddress, targetIp);
File targetFile = new File(targetFilePath);
File sourceFile = new File(currentPath);
fileChannelCopy(sourceFile, targetFile);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (buff != null) {
try {
buff.close();
buff = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
/**
* 將某個配置文件中的所有數據封裝成List
* @param file
* @return
*/
public static List<String> getAllLineFromFile(File file) {
try {
FileReader fr = new FileReader(file.getPath());
BufferedReader br = new BufferedReader(fr);
List<String> allLineTxt = new ArrayList<String>();
String lineText = "";
while ((lineText = br.readLine()) != null) {
allLineTxt.add(lineText);
}
fr.close();
return allLineTxt;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 配置文件管理員工具功能修改配置文件files.txt的業務功能描述
* @param filePath 文件路徑
* @param fileDescription 文件業務功能描述信息
* @return true/false
*/
public static boolean saveFilesTxtContent(String filePath, String fileDescription) {
BufferedOutputStream buff = null;
try {
String wthome =
"D:\\ptc\\Windchill_10.0\\Windchill";
//(String) (WTProperties.getLocalProperties()).getProperty("wt.home", "");
filePath = filePath.replace("wt_home", wthome);
File files4Txt = new File(wthome + File.separator + "codebase" + File.separator + "files.txt");
if (files4Txt.isFile() && files4Txt.exists()) {
//將文件所有行數據封裝爲總的LIST
List<String> filesTxtContext = getAllLineFromFile(files4Txt);
if(filesTxtContext.size()==0) {
return false;
}
//迭代這個list的每一行數據
for (int i=0; i<filesTxtContext.size(); i++) {
String lineText = filesTxtContext.get(i);
//獲取當前行數據的文件名稱,文件業務功能描述,文件路徑
String[] fileNameAndFilePath = lineText.split(" ");
//如果當前行的數據文件路徑和傳進來的文件路徑一致
if (fileNameAndFilePath.length == 3 && filePath.equals(fileNameAndFilePath[2])) {
//把當前行數據的文件描述部分替換爲頁面傳遞進來的文件業務功能描述
String newLineText = lineText.replace(fileNameAndFilePath[1], fileDescription);
//替換掉總list的這條數據
filesTxtContext.remove(i);
filesTxtContext.add(i,newLineText);
break;
}
}
if (files4Txt.canRead() && files4Txt.canWrite()) {
buff = new BufferedOutputStream(new FileOutputStream(files4Txt));
for (String lineText : filesTxtContext) {
//將新的總數據list寫入文件
buff.write(lineText.getBytes());
buff.write("\r\n".getBytes());
}
}
buff.flush();
buff.close();
return true;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (buff != null) {
try {
buff.close();
buff = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
/**
* 獲取指定目錄下的所有文件,過濾掉temp/uploaded_file/bak/backup目錄 僅收集".txt", ".properties",
* ".xls", ".xlsx", ".xml", ".xconf", ".vm"類型文件
*
* @param srcFolder 目錄
* @param configFileInfo List<Map<文件名稱,文件路徑>>集合
* @return 所有文件的信息List<Map<文件名稱,文件路徑>>
* @throws JSONException
* @throws IOException
*/
public static List<Map<String, String>> getAllFilesByPath(File srcFolder, List<Map<String, String>> configFileInfo)
throws JSONException, IOException {
// 獲取該目錄下所有的文件或者文件夾的File數組
File[] fileArray = srcFolder.listFiles();
// 遍歷該File數組,得到每一個File對象
if (configFileInfo == null) {
configFileInfo = new ArrayList<Map<String, String>>();
}
if (fileArray.length != 0) {
for (File file : fileArray) {
// 判斷該File對象是否是文件夾
if (file.isDirectory()) {
if (isNeedCollectionFiloder(file)) {
getAllFilesByPath(file, configFileInfo);
}
} else {
if (isNeedCollectionFile(file.getName())) {
Map<String, String> lineStr = new HashMap<String, String>();
lineStr.put("fileName", file.getName());
lineStr.put("fileDescription", "TODO:configFile for item/bom/process/iba/partNumber.");
String wthome = (String) (WTProperties.getLocalProperties()).getProperty("wt.home", "");
String filePath = file.getAbsolutePath().replace(wthome, "wt_home");
lineStr.put("filePath", filePath);
configFileInfo.add(lineStr);
}
}
}
}
return configFileInfo;
}
/**
* 讀取 wt_home/codebase/files.txt 文件,將系統的業務配置文件顯示到管理員工具頁面 頁面包含文件名稱,文件業務描述,文件路徑
*
* @return
*/
public static List<Map<String, String>> getPlmBussnessConfigFiles4FileTxt() {
List<Map<String, String>> bussnessConfigFiles = new ArrayList<Map<String, String>>();
BufferedReader br = null;
try {
String wthome = (String) (WTProperties.getLocalProperties()).getProperty("wt.home", "");
File file = new File(wthome + File.separator + "codebase" + File.separator + "files.txt");
if (file.isFile() && file.exists()) {
br = new BufferedReader(new InputStreamReader(new FileInputStream(file), "utf-8"));
String lineText = null;
while ((lineText = br.readLine()) != null) {
Map<String, String> fileInfo4Current = new HashMap<String, String>();
String[] fileNameAndFilePath = lineText.split(" ");
if (fileNameAndFilePath.length == 3) {
fileInfo4Current.put("fileName", fileNameAndFilePath[0]);
fileInfo4Current.put("fileDescription", fileNameAndFilePath[1]);
fileInfo4Current.put("filePath", fileNameAndFilePath[2]);
bussnessConfigFiles.add(fileInfo4Current);
}
}
br.close();
br = null;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
br = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
return bussnessConfigFiles;
}
/**
* 是否爲需要的目錄
*
* @param file
* @return
*/
private static boolean isNeedCollectionFiloder(File file) {
if (file.getPath().endsWith("temp")) {
return false;
}
if (file.getPath().endsWith("uploaded_file")) {
return false;
}
if (file.getPath().endsWith("bak")) {
return false;
}
if (file.getPath().endsWith("backup")) {
return false;
}
return true;
}
/**
* 是否爲需要的文件類型
*
* @param fileName
* @return
*/
private static boolean isNeedCollectionFile(String fileName) {
if (fileName.contains(".class") || fileName.contains(".jar") || fileName.contains(".bak")
|| fileName.contains("back")) {
return false;
}
if (fileName.endsWith("bak") || fileName.endsWith("back")) {
return false;
}
if (fileName.lastIndexOf(".") == -1) {
return false;
}
String fileType = fileName.substring(fileName.lastIndexOf("."), fileName.length());
if (!fileFiter.contains(fileType)) {
return false;
}
return true;
}
}