最近在工做中遇到了這樣一個問題:前臺的客戶端程序須要在後臺指定程序更新後清空本地的緩存,後臺程序的數量不止一個。這個問題的癥結在於客戶端程序並不知道後臺程序是何時更新的,爲了解決這個問題,我想了以下的辦法:java
一、在配置表中設立配置項,保存後臺程序的版本號,每次後臺程序更新時,將這個版本號也同步更新sql
二、前臺客戶端程序也保存一組後臺程序的版本號,每次登陸程序後讀取配置表中的版本號,兩者進行比較,若是有一組版本號不匹配,則說明後臺程序有變更,前臺客戶端就須要清空本地的緩存數據了緩存
本次製做的小工具,功能就是在上面的第1步時,根據XML的配置生成若干個SQL語句(merge語句),用於更新配置表中的對應配置項。設計這個工具的目的,一是在修改SQL語句的時候能夠避免因馬虎等因素形成的語句書寫錯誤,二是同時生成一次語句後能夠分享給多我的在多個環境上同時進行升級。app
這個小工具是用Java語言寫的,工程以下:函數
文件version.xml存儲了咱們準備配置的版本號信息工具
<?xml version="1.0" encoding="UTF-8"?> <systems author="Tsybius2014" output="updateVer.sql" remark="none"> <!-- 系統1 --> <system config_no="110020" name="System1" version="v1.2.0.1" enabled="true" /> <!-- 系統2 --> <system config_no="110021" name="System2" version="v1.2.3.4" enabled="true" /> <!-- 系統3 --> <system config_no="110022" name="System3" version="v1.0.0.1" enabled="false" /> </systems>
各配置項說明以下:ui
一、output爲輸出的sql文件路徑spa
二、author爲做者信息、remark爲備註信息,這兩個信息會出如今生出的sql腳本的首部,以註釋形式出現設計
三、每一個system節點配置了一個系統,config_no爲配置項編號,name爲配置項說明,version爲該系統的版本號,enabled爲程序執行時是否生成該系統的MergeInto語句調試
要將version.xml的內容生成爲MergeInto語句,還須要一個模板,我將它放在文件template.txt中,內容以下:
MERGE INTO INTERINS.SYS_CONFIG CONFIG USING (SELECT #{config_no} AS CONFIG_NO, '11' AS SUB_SYS_CODE, #{name} AS CONFIG_NAME, '0' AS MANAGE_LEVEL, '0' AS ACCESS_LEVEL, '2' AS DATA_TYPE, #{version} AS STR_CONFIG, '1' AS CONFIG_STATUS, TO_CHAR(SYSDATE,'yyyy-MM-dd HH:mm:ss') AS DATETIME FROM DUAL) INPUT ON (CONFIG.CONFIG_NO = INPUT.CONFIG_NO) WHEN MATCHED THEN UPDATE SET CONFIG.SUB_SYS_CODE = INPUT.SUB_SYS_CODE, CONFIG.CONFIG_NAME = INPUT.CONFIG_NAME, CONFIG.DATA_TYPE = INPUT.DATA_TYPE, CONFIG.STR_CONFIG = INPUT.STR_CONFIG, CONFIG.CONFIG_STATUS = INPUT.CONFIG_STATUS, CONFIG.REMARK = 'UPDATE BY GEN_MERGE_INTOS ON ' || INPUT.DATETIME WHEN NOT MATCHED THEN INSERT (CONFIG_NO, SUB_SYS_CODE, CONFIG_NAME, MANAGE_LEVEL, ACCESS_LEVEL, DATA_TYPE, STR_CONFIG, CONFIG_STATUS, REMARK) VALUES (INPUT.CONFIG_NO, INPUT.SUB_SYS_CODE, INPUT.CONFIG_NAME, INPUT.MANAGE_LEVEL, INPUT.ACCESS_LEVEL, INPUT.DATA_TYPE, INPUT.STR_CONFIG, INPUT.CONFIG_STATUS, 'INSERT BY GEN_MERGE_INTOS ON ' || INPUT.DATETIME);
其中,用config_no替換#{config_no},用name替換#{name},用version替換#{version},就能夠生成對應的MergeInto語句了。
GenMergeIntos.java代碼以下:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedList; import java.util.Queue; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; /** * SQL腳本生成工具 - 用於系統版本升級後刷新緩存 * * @文件名稱 GenMergeIntos.java * @文件做者 Tsybius2014 * @建立時間 2016年2月15日 上午11:01:51 */ public class GenMergeIntos { // 輸出文件地址(需從配置文件中讀取) static String outputPath = ""; // 輸出文件做者(需從配置文件中讀取) static String author = ""; // 備註信息(需從配置文件中讀取) static String remark = ""; // 配置文件地址 - 調試時請修改成 src\\version.xml static String configPath = "version.xml"; // 模板文件地址 - 調試時請修改成 src\\template.xml static String templatePath = "template.txt"; // 生成的SQL語句暫存於此 static Queue<String> mergeIntos = null; public static void main(String[] args) { //mergeInto語句模板 final String template = getTemplate(templatePath); //存儲mergeInto語句 mergeIntos = new LinkedList<String>(); // 設置句柄 DefaultHandler handler = new DefaultHandler() { // XML文檔開始讀取時觸發 public void startDocument() { System.out.println("---------XML文檔解析開始---------"); } // XML文檔讀取結束時觸發 public void endDocument() { System.out.println("---------XML文檔解析結束---------"); } // 讀取到某一元素時觸發 public void startElement(String namespaceURI, String lname, String qname, Attributes attrs) { if (qname.equals("systems")) { System.out.println("文件輸出路徑:" + attrs.getValue("output")); outputPath = attrs.getValue("output"); System.out.println("做者:" + attrs.getValue("author")); author = attrs.getValue("author"); System.out.println("備註:" + attrs.getValue("remark")); remark = attrs.getValue("remark"); } else if (qname.equals("system")) { if (attrs.getValue("enabled").toLowerCase().equals("true")) { System.out.print("讀取配置:" + attrs.getValue("name") + "; "); System.out.print("版本號:" + attrs.getValue("version") + "; "); System.out.println("配置號:" + attrs.getValue("config_no")); mergeIntos.add(getMergeInto(template, attrs.getValue("name"), attrs.getValue("version"), attrs.getValue("config_no"))); } } } }; // 使用SAX解析XML SAXParserFactory factory = SAXParserFactory.newInstance(); factory.setNamespaceAware(false); try { File configFile = new File(configPath); SAXParser saxParser = factory.newSAXParser(); saxParser.parse(configFile, handler); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } outputMergeIntos(); System.out.println("程序運行結束"); } /** * 獲取模板 * * @param templatePath * @return */ public static String getTemplate(String templatePath) { String template = ""; try { System.out.println("正在輸出到文件" + outputPath); StringBuilder buffer = new StringBuilder(); InputStream is = new FileInputStream(templatePath); String line; BufferedReader reader = new BufferedReader( new InputStreamReader(is)); line = reader.readLine(); while (line != null) { buffer.append(line); buffer.append("\n"); line = reader.readLine(); } template = buffer.toString(); reader.close(); is.close(); System.out.println("輸出完畢" + outputPath); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return template; } /** * 經過模板生成對應SQL語句 * * @param template * 模板 * @param name * 配置名 * @param version * 版本號 * @param configNo * 配置號 * @return */ public static String getMergeInto(String template, String name, String version, String configNo) { String result = template; result = result.replaceAll("\\#\\{name\\}", "'" + name + "'"); result = result.replaceAll("\\#\\{version\\}", "'" + version + "'"); result = result.replaceAll("\\#\\{config_no\\}", "'" + configNo + "'"); return result; } /** * 將數據輸出到文件 */ public static void outputMergeIntos() { try { System.out.println("正在導出到文件:" + outputPath); File outputFile = new File(outputPath); BufferedWriter bw = new BufferedWriter(new PrintWriter(outputFile)); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String currDateTime = sdf.format(new Date()); bw.append("-----------------------------------------------------\n"); bw.append("-- 各子系統相關版本號配置項更新\n"); bw.append("-- 建立時間:" + currDateTime + "\n"); bw.append("-- 建立人員:" + author + "\n"); bw.append("-- 備註信息:" + remark + "\n"); bw.append("-----------------------------------------------------\n"); bw.newLine(); for (String mergeInto : mergeIntos) { bw.append(mergeInto); bw.newLine(); } bw.append("-- 完"); bw.close(); System.out.println("導出完畢"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
生成jar包並使用的步驟以下:
一、鼠標右鍵單擊項目,在彈出菜單中點擊Export
二、嚮導頁第一頁,選擇Java→JAR file,點擊Next
三、選擇剛纔正在修改的項目,並在下方「JAR file」位置指定輸出的Jar包所在的地址,點擊Next
四、這一步直接點擊Next
五、點擊Browse按鈕,指定JAR包入口點
六、找到main函數所在的類,點擊OK按鈕
七、生成的jar包旁邊,創建一個bat文件「GenMergeIntos.bat」,代碼以下:
@java -jar GenMergeIntos.jar @pause
八、運行這個bat文件,運行效果以下:
九、生成的sql文件(updateVer.sql)以下
END