mybatis動態更新xml文件后熱部署,不重啟應用的方法

mybatis應用程序,由于是半自動化的sql, 有大量的sql是在xml文件中配置的,而在開發程序的過程中,通常需要邊寫sql變調試應用。但在默認情況下,xml文件里配置的sql語句是被放入到緩存中去了,每次更改有sql語句的xml文件,需要重新啟動應用,這樣工作效率很低,于是很希望有一個動態加載xml文件的功能,自動加載新的sql語句,并重新寫入到緩存中,在網上參考了很多資料,最終弄了一個簡單的東西出來,直接寫成了spring mvc的controller。代碼如下:?
?

package com.yihaomen.controller;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Scope("prototype")
@Controller
@RequestMapping("/sql")
public class SQLSessionCacheController {private Log log  = LogFactory.getLog(SQLSessionCacheController.class);@Autowiredprivate SqlSessionFactory sqlSessionFactory;private Resource[] mapperLocations;private String packageSearchPath = "classpath*:**/mappers/*.xml";private HashMap<String, Long> fileMapping = new HashMap<String, Long>();// 記錄文件是否變化@RequestMapping("/refresh")@ResponseBodypublic String refreshMapper() {try {Configuration configuration = this.sqlSessionFactory.getConfiguration();// step.1 掃描文件try {this.scanMapperXml();} catch (IOException e) {log.error("packageSearchPath掃描包路徑配置錯誤");return "packageSearchPath掃描包路徑配置錯誤";}System.out.println("==============刷新前mapper中的內容===============");for (String name : configuration.getMappedStatementNames()) {System.out.println(name);}// step.2 判斷是否有文件發生了變化if (this.isChanged()) {// step.2.1 清理this.removeConfig(configuration);// step.2.2 重新加載for (Resource configLocation : mapperLocations) {try {XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configLocation.getInputStream(), configuration, configLocation.toString(), configuration.getSqlFragments());xmlMapperBuilder.parse();log.info("mapper文件[" + configLocation.getFilename() + "]緩存加載成功");} catch (IOException e) {log.error("mapper文件[" + configLocation.getFilename() + "]不存在或內容格式不對");continue;}}}System.out.println("==============刷新后mapper中的內容===============");for (String name : configuration.getMappedStatementNames()) {System.out.println(name);}return "刷新mybatis xml配置語句成功";} catch (Exception e) {e.printStackTrace();return "刷新mybatis xml配置語句失敗";}}public void setPackageSearchPath(String packageSearchPath) {this.packageSearchPath = packageSearchPath;}public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}/*** 掃描xml文件所在的路徑* @throws IOException */private void scanMapperXml() throws IOException {this.mapperLocations = new PathMatchingResourcePatternResolver().getResources(packageSearchPath);}/*** 清空Configuration中幾個重要的緩存* @param configuration* @throws Exception*/private void removeConfig(Configuration configuration) throws Exception {Class<?> classConfig = configuration.getClass();clearMap(classConfig, configuration, "mappedStatements");clearMap(classConfig, configuration, "caches");clearMap(classConfig, configuration, "resultMaps");clearMap(classConfig, configuration, "parameterMaps");clearMap(classConfig, configuration, "keyGenerators");clearMap(classConfig, configuration, "sqlFragments");clearSet(classConfig, configuration, "loadedResources");}@SuppressWarnings("rawtypes")private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {Field field = classConfig.getDeclaredField(fieldName);field.setAccessible(true);Map mapConfig = (Map) field.get(configuration);mapConfig.clear();}@SuppressWarnings("rawtypes")private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {Field field = classConfig.getDeclaredField(fieldName);field.setAccessible(true);Set setConfig = (Set) field.get(configuration);setConfig.clear();}/*** 判斷文件是否發生了變化* @param resource* @return* @throws IOException*/private boolean isChanged() throws IOException {boolean flag = false;for (Resource resource : mapperLocations) {String resourceName = resource.getFilename();boolean addFlag = !fileMapping.containsKey(resourceName);// 此為新增標識// 修改文件:判斷文件內容是否有變化Long compareFrame = fileMapping.get(resourceName);long lastFrame = resource.contentLength() + resource.lastModified();boolean modifyFlag = null != compareFrame && compareFrame.longValue() != lastFrame;// 此為修改標識// 新增或是修改時,存儲文件if(addFlag || modifyFlag) {fileMapping.put(resourceName, Long.valueOf(lastFrame));// 文件內容幀值flag = true;}}return flag;}
}



注意事項:?
在我的應用中,mybatis配置文件放在這里的:classpath*:**/mappers/*.xml, 因此我定義死了,需要修改成自己的路徑.?

測試方法:?
可以通過controller提供的地址,直接在瀏覽器上輸入url訪問, 比如:?http://localhost:8080/sql/refresh?, 當然,你還可以通過js用ajax方式調用,都是可以的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/386773.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/386773.shtml
英文地址,請注明出處:http://en.pswp.cn/news/386773.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Leetcode 反轉字符串 II python解法

題干&#xff1a; 給定一個字符串 s 和一個整數 k&#xff0c;從字符串開頭算起&#xff0c;每計數至 2k 個字符&#xff0c;就反轉這 2k 字符中的前 k 個字符。 如果剩余字符少于 k 個&#xff0c;則將剩余字符全部反轉。 如果剩余字符小于 2k 但大于或等于 k 個&#xff0c;…

下拉插件 (帶搜索) Bootstrap-select 從后臺獲取數據填充到select的 option中 用法詳解...

今天收到了客戶的需求&#xff0c;要求在新增停車場ID的時候要從數據庫查出來對應的停車場名稱然后顯示在界面上。保存的時候按照停車場ID進行保存。 自己首先把后臺的部分寫完了&#xff0c;測試了接口數據。成功的拿到了ajax數據。 接下來&#xff0c;自己用了select下拉標簽…

pytorch tensorboard基本用法整理

from torch.utils.tensorboard import SummaryWriterif __name__ __main__:aa SummaryWriter(logs) # 創建保存了summarywriter的log目錄for i in range(100):aa.add_scalar(y x, i, i) # 后兩個參數先y軸后x軸 x軸往往是global step y軸用于輸出loss或者其他需要觀察的變量…

php 支付寶付款接口測試

詳細去這里&#xff1a;https://blog.csdn.net/suprezheng/article/details/84931225 轉載于:https://www.cnblogs.com/LF-place/p/10898357.html

spring boot mybatis攔截器

mybaits攔截器 package com.chinamobile.scm.masterdata.interceptor;import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apach…

Linux自有服務(2)-Linux從入門到精通第六天(非原創)

文章大綱 一、設置主機名二、chkconfig三、ntp服務四、防火墻服務五、rpm管理&#xff08;重點&#xff09;六、cron/crontab計劃任務&#xff08;重點&#xff09;七、學習資料下載八、參考文章 自有服務&#xff0c;即不需要用戶獨立去安裝的軟件的服務&#xff0c;而是當系統…

Spring 事務 以及攔截器的前后關系實驗 Mybatis 日志攔截

背景&#xff1a;當一個線程中&#xff0c;如果需要攔截所有當SQL日志&#xff0c;然后統一發送到一個同步器&#xff0c;就可以實現多個數據庫實現同步主庫&#xff0c;在進行紅綠上線&#xff0c;或者灰度部署時候&#xff0c;可以實現生產庫與測試庫實時同步&#xff0c;從而…

四級翻譯常用詞匯

ancient 古老的&#xff1b;古代的       achieve 獲得 v attract 吸引 v            achievement 成就 n attractive 吸引人的          advanced 先進的 account for 對....負有責任&#xff1b;占比   approach 接近&#xff1b;處理&#…

一般攔截器 serviceImpl部分

一般攔截器 serviceImpl部分 package com.chinamobile.scm.masterdata.interceptor;import com.chinamobile.framework.common.context.InvokeTracer; import com.chinamobile.framework.common.context.RequestContext; import com.chinamobile.framework.utils.CollectionUt…

營銷-營銷方式:營銷方式

ylbtech-營銷-營銷方式&#xff1a;營銷方式營銷方式是指營銷過程中所有可以使用的方法。包括服務營銷、體驗營銷、知識營銷、情感營銷、教育營銷、差異化營銷、直銷、網絡營銷等。要有好的營銷方式首先要創造行之有效的營銷工具。但這并不意味著要把預算的75%都花在印制宣傳資…

以后可能用到的一些OQL

Visual VM對OQL的支持 上面我們學會了如何查看堆內存快照&#xff0c;但是&#xff0c;堆內存快照十分龐大&#xff0c;快照中的類數量也很多。Visual VM提供了對OQL&#xff08;對象查詢語言&#xff09;的支持&#xff0c;以便于開發人員在龐大的堆內存數據中&#xff0c;快…

leetcode1041困于環中的機器人

題目如下&#xff0c;一道簡單的模擬 在無限的平面上&#xff0c;機器人最初位于 (0, 0) 處&#xff0c;面朝北方。機器人可以接受下列三條指令之一&#xff1a;"G"&#xff1a;直走 1 個單位 "L"&#xff1a;左轉 90 度 "R"&#xff1a;右轉 90…

一個拆分使用的存儲過程例子

set serverout on declare var_tmp varchar2(4000) :; var_element varchar2(4000) :; n_length Number : length(\/); begin values_array : VARCHAR_ARRAY(); -- 初始化數組 for i in (select * from sapsr3.zmdm_mthdr where zmtpre in(6200001…

python的pwntools工具的日常使用

1.安裝 操作系統&#xff1a; ubuntu16.04 環境準備&#xff1a; pythonpiplibssl-devlibffi-dev pwntools安裝&#xff1a; sudo apt-get install libffi-devsudo apt-get install libssl-devsudo apt-get install pythonsudo apt-get install python-pipsudo pip install pwn…

Kibana可視化管理頁面詳細使用說明

Kibana可視化管理頁面詳細使用說明 使用瀏覽器訪問 ip:5601 默認端口&#xff0c;進入首頁 Discover&#xff1a;日志管理視圖 主要進行搜索和查詢 Visualize&#xff1a;統計視圖 構建可視化的圖表 Dashboard&#xff1a;儀表視圖 將構…

OO_BLOG3_規格化設計(JML學習)

目錄 JML語言學習筆記理論基礎應用工具鏈情況JMLUnit/JMLUnitNGUNIT3 作業分析作業 3-1 實現兩個容器類Path和PathContainer作業 3-2 實現容器類Path和數據結構類Graph作業 3-3 實現容器類Path&#xff0c;地鐵系統類RailwaySystem規格撰寫的心得與體會最后&#xff0c;衷心感謝…

JAVA獲取JVM內存空間和物理內存空間

一、獲取JVM內存空間 系統環境&#xff1a;WIN JDK版本&#xff1a;1.8re 直接調用Runtime中相應的方法即可&#xff1a; public long maxMemory() Returns the maximum amount of memory that the Java virtual machine will attempt to use. If there is no inherent lim…

CMU Database Systems - Sorting,Aggregation,Join

Sorting 排序如果可在內存里面排&#xff0c;用經典的排序算法就ok&#xff0c;比如快排 問題在于&#xff0c;數據表中的的數據是很多的&#xff0c;沒法一下都放到內存里面進行排序 所以就需要用到&#xff0c;外排&#xff0c;多路并歸排序 看下最簡單的&#xff0c;2路并歸…

springboot線程池的使用和擴展

實戰環境 windowns10&#xff1b;jdk1.8&#xff1b;springboot 1.5.9.RELEASE&#xff1b;開發工具&#xff1a;IntelliJ IDEA&#xff1b; 實戰源碼 本次實戰的源碼可以在我的GitHub下載&#xff0c;地址&#xff1a;gitgithub.com:zq2599/blog_demos.git&#xff0c;項目主…

統計單詞個數

我是抄題解狂魔 /* 1.s.substr(x,len) 在s中取出從x位置開始&#xff0c;長度為len的字符串&#xff0c;并返回string類型的字符串。 2.s.find(a) 在s中查找字符串a,并返回起始下標&#xff08;從0開始&#xff09;&#xff0c;若不存在&#xff0c;返回1844674407370955161&am…