范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

分享一个修改了xml文件再也不用重启的项目mybatisxmlrelaod

  自我18年使用 Mybaits 以来,开发环境中如果修改了 xml 文件后,只有重启项目才能生效,如果小项目重启还好,但是对于一个重启需要十几分钟的大型项目来说,这就非常耗时了。开发人员因为修改了xml 文件少量内容,比如添加一个逗号、查询增加一个字段或者修改一个 bug 等,就需要重启整个项目,这就非常痛苦了。
  所以在这里给大家推荐一个实现了 Mybatis xml文件热加载的项目, 「mybatis-xmlreload-spring-boot-starter」 。它能够帮助我们在「Spring Boot + Mybatis」 的开发环境中修改 xml 后,不需要重启项目就能让修改过后 xml 文件立即生效,实现热加载功能。这里给出项目地址: https://github.com/wayn111/mybatis-xmlreload-spring-boot-starter 欢迎大家关注,点个star
  ps: 「mybatis-xmlreload-spring-boot-starter」 目前 3.0.3.m1 版本实现了 xml 文件修改已有内容,比如修改 sql 语句、添加查询字段、添加查询条件等,可以实现热加载功能。但是对于 xml 文件添加 insert|update|delete|select  标签等内容后,是无法实现热加载的。众所周知,在 Idea 环境进行 Java 开发,在方法内修改方法内容是可以热加载的。但是添加新方法、添加方法参数,修改方法参数,修改方法返回值等都是无法直接热加载的。 一、mybatis-xmlreload-spring-boot-starter使用
  「mybatis-xmlreload-spring-boot-starter」 原理: 修改 xml 文件的加载逻辑。在普通的  mybatis-spring  项目中,默认只会加载项目编译过后的 xml 文件,也就是 target 目录下的 xml 文件。但是在「mybatis-xmlreload-spring-boot-starter」 中,修改了这一点,它会加载项目 resources 目录下的 xml 文件,这样用户对于 resources 目录下 xml 文件的修改操作是可以立即触发热加载的。 通过  io.methvin.directory-watcher  项目来监听 xml 文件的修改操作,它底层是通过 java.nio 的WatchService  来实现,当我们监听了整个 resources 目录后,xml 文件的修改会立马触发 MODIFY 事件。 通过  mybatis-spring  项目原生的 xmlMapperBuilder.parse()  方法重新加载解析修改过后的 xml 文件来保证项目对于 Mybatis 的兼容性处理。 二、技术原理
  「mybatis-xmlreload-spring-boot-starter」 代码结构如下:
  核心代码在 「MybatisXmlReload」 类中,执行逻辑: 通过项目初始化时传入  MybatisXmlReloadProperties prop, List sqlSessionFactories  参数,获取「mybatis-xmlreload-spring-boot-starter」 的配置信息,以及项目中的数据源配置 /**  * 是否启动以及xml路径的配置类  */ private MybatisXmlReloadProperties prop; /**  * 获取项目中初始化完成的SqlSessionFactory列表,对多数据源进行处理  */ private List sqlSessionFactories; public MybatisXmlReload(MybatisXmlReloadProperties prop,          List sqlSessionFactories) {     this.prop = prop;     this.sqlSessionFactories = sqlSessionFactories; }解析配置文件指定的 xml 路径,获取 xml 文件在 target 目录下的位置  // 解析项目所有xml路径,获取xml文件在target目录中的位置 List mapperLocationsTmp = Stream.of(   Optional.of(prop.getMapperLocations())   .orElse(new String[0]))   .flatMap(location -> Stream.of(getResources(patternResolver, location)))   .toList();根据 xml 文件在 target 目录下的位置,进行路径替换找到 xml 文件所在 resources 目录下的位置  // 根据xml文件在target目录下的位置,进行路径替换找到该xml文件在resources目录下的位置 for (Resource mapperLocation : mapperLocationsTmp) {     mapperLocations.add(mapperLocation);     String absolutePath = mapperLocation.getFile().getAbsolutePath();     File tmpFile = new File(absolutePath.replace(CLASS_PATH_TARGET,       MAVEN_RESOURCES));     if (tmpFile.exists()) {         locationPatternSet.add(Path.of(tmpFile.getParent()));         FileSystemResource fileSystemResource =            new FileSystemResource(tmpFile);         mapperLocations.add(fileSystemResource);     } }对 resources 目录的 xml 文件的修改操作进行监听  // 对resources目录的xml文件修改进行监听 List rootPaths = new ArrayList<>(); rootPaths.addAll(locationPatternSet); DirectoryWatcher watcher = DirectoryWatcher.builder()     .paths(rootPaths) // or use paths(directoriesToWatch)     .listener(event -> {         switch (event.eventType()) {             case CREATE: /* file created */                 break;             case MODIFY: /* file modified */                 Path modifyPath = event.path();                 String absolutePath = modifyPath.toFile().getAbsolutePath();                 logger.info("mybatis xml file has changed:" + modifyPath);                 // 执行热加载逻辑...                 break;             case DELETE: /* file deleted */                 break;         }     })     .build(); ThreadFactory threadFactory = r -> {     Thread thread = new Thread(r);     thread.setName("xml-reload");     thread.setDaemon(true);     return thread; }; watcher.watchAsync(new ScheduledThreadPoolExecutor(1, threadFactory));对多个数据源进行遍历,判断修改过的 xml 文件属于那个数据源  // 对多个数据源进行遍历,判断修改过的xml文件属于那个数据源 for (SqlSessionFactory sqlSessionFactory : sqlSessionFactories) {     ... }根据 Configuration 对象获取对应的标签属性  // 根据 Configuration 对象获取对应的标签属性 Configuration targetConfiguration = sqlSessionFactory.getConfiguration(); Class<?> tClass = targetConfiguration.getClass(),    aClass = targetConfiguration.getClass(); if (targetConfiguration.getClass().getSimpleName()                                   .equals("MybatisConfiguration")) {     aClass = Configuration.class; } Set loadedResources = (Set) getFieldValue(     targetConfiguration, aClass, "loadedResources"); loadedResources.clear();  Map resultMaps = (Map) getFieldValue(     targetConfiguration, tClass, "resultMaps"); Map sqlFragmentsMaps = (Map) getFieldValue(     targetConfiguration, tClass, "sqlFragments"); Map mappedStatementMaps =      (Map) getFieldValue(         targetConfiguration, tClass, "mappedStatements");遍历 resources 目录下 xml 文件列表  // 遍历 resources 目录下 xml 文件列表 for (Resource mapperLocation : mapperLocations) {     ... }判断是否是被修改过的 xml 文件,否则跳过  // 判断是否是被修改过的xml文件,否则跳过 if (!absolutePath.equals(mapperLocation.getFile().getAbsolutePath())) {     continue; }解析xml文件,获取修改后的xml文件标签对应的  resultMaps|sqlFragmentsMaps|mappedStatementMaps  的属性并执行替换逻辑,并且兼容 mybatis-plus  的替换逻辑 // 重新解析xml文件,替换Configuration对象的相对应属性 XPathParser parser = new XPathParser(mapperLocation.getInputStream(),      true,      targetConfiguration.getVariables(),      new XMLMapperEntityResolver()); XNode mapperXnode = parser.evalNode("/mapper"); String namespace = mapperXnode.getStringAttribute("namespace"); List resultMapNodes = mapperXnode.evalNodes("/mapper/resultMap"); for (XNode xNode : resultMapNodes) {     String id =          xNode.getStringAttribute("id", xNode.getValueBasedIdentifier());     resultMaps.remove(namespace + "." + id); }  List sqlNodes = mapperXnode.evalNodes("/mapper/sql"); for (XNode sqlNode : sqlNodes) {     String id =          sqlNode.getStringAttribute("id", sqlNode.getValueBasedIdentifier());     sqlFragmentsMaps.remove(namespace + "." + id); }  List msNodes = mapperXnode.evalNodes("select|insert|update|delete"); for (XNode msNode : msNodes) {     String id =          msNode.getStringAttribute("id", msNode.getValueBasedIdentifier());     mappedStatementMaps.remove(namespace + "." + id); }重新加载和解析被修改的 xml 文件  // 9. 重新加载和解析被修改的 xml 文件 try {     XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(         mapperLocation.getInputStream(),         targetConfiguration,         mapperLocation.toString(),          targetConfiguration.getSqlFragments());     xmlMapperBuilder.parse(); } catch (Exception e) {     logger.error(e.getMessage(), e); }三、安装方式在  Spring Boot3.0  中,「mybatis-xmlreload-spring-boot-starter」 在 Maven 项目提供坐标地址如下:      com.wayn     mybatis-xmlreload-spring-boot-starter     3.0.3.m1 在  Spring Boot2.0  Maven 项目提供坐标地址如下:      com.wayn     mybatis-xmlreload-spring-boot-starter     2.0.1.m1 四、使用配置
  「mybatis-xmlreload-spring-boot-starter」  目前只有两个配置属性。mybatis-xml-reload.enabled  默认是 false, 也就是不启用 xml 文件的热加载功能,想要开启的话通过在项目配置文件中设置 mybatis-xml-reload.enabled  为 true。还有一个配置属性是 mybatis-xml-reload.mapper-locations ,执行热加载的 xml 文件路径,这个属性需要手动填写,跟项目中的 mybatis.mapper-locations  保持一直即可。具体配置如下: # mybatis xml文件热加载配置 mybatis-xml-reload:   # 是否开启 xml 热更新,true开启,false不开启,默认为false   enabled: true    # xml文件路径,可以填写多个,逗号分隔。   # eg: `classpath*:mapper/**/*Mapper.xml,classpath*:other/**/*Mapper.xml`   mapper-locations: classpath:mapper/*Mapper.xml五、最后
  欢迎大家使用 「mybatis-xmlreload-spring-boot-starter」 ,这个项目我开源的的,使用中遇到问题可以提交 issue。提交的问题我都会一一查看并回复。再附项目地址: https://github.com/wayn111/mybatis-xmlreload-spring-boot-starter
  最后再说一句,感兴趣的朋友可以点赞加关注,你的支持将是我更新动力。

表面是艺人,实际是富二代的6位明星,混不下去就得继承上亿家产文阅栀编辑阅栀该税的税,不该睡的别睡。这句话放在娱乐圈,重量堪比当年的劝学了!尤其在税这个问题上,很多明星都是为了一己私欲,把钱看得比名重要,才行差踏错,落了个失德艺人的称号。但娱三星GalaxyZFold4折叠屏手机体验,再进一步的旗舰折叠屏手机头条群星8月榜目前市面上已经发布的折叠屏手机我基本都体验过,包括vivoXFold荣耀MagicVOPPOFindN等,而这些折叠屏手机给我的感受,明显的缺点除了厚重折痕以外,依旧如何穿出秋天的质感,这篇最全郁达夫在古都的秋中提笔便写秋天,无论什么地方的秋天,总是好的。秋天,是四季中最有色彩的季节。万千色彩翻涌不已,苍翠葱茏滚滚而去。秋天也是气味最馥郁的季节,果香花香木香泥土与远山森林田震国外大街上兴奋遛狗!穿破洞裤打扮潮流,涂大红唇气场强大近日,著名歌手田震在社交平台晒出自己的惬意生活,视频中她与自己的爱宠狗狗开心玩耍,看起来好愉快!看她最近的状态,可谓是越活越年轻,田震身穿绿色卫衣,头戴白色鸭舌帽,还把墨镜时尚得卡FERRAGAMO更名焕新,年轻化战略初见成效图片来源FERRAGAMO上周,正值米兰时装周拉开帷幕之际,意大利老牌时装屋SalvatoreFerragamo宣布正式更名为FERRAGAMO,品牌全新logo由著名平面设计师P男士相亲戴什么手表好?头条创作挑战赛相亲作为重要场合,展现自我良好的精神风貌和经济实力,还是很有必要的。好好收拾一下再出现,不仅可以提高相亲的成功率,也是对自己对相亲对象对介绍人的尊重。手表作为体现个人演员吴春怡晒杀青照,穿高叉裙大秀好身材,美腿白皙修长太抢镜9与26日,素有中国第一美腿车模之称的超模兼演员吴春怡,晒出自己与剧组演员的杀青照,凹凸有致的性感身材让人羡慕。电影杀青,吴春怡捧着鲜花心情大好,对着镜头大秀好身材,皮肤白皙,身材那英现身米兰时装秀,穿黑装大佬气场全开,她紧挨的男子引起大家注意近日,歌手那英现身米兰时装周看秀。一组她在米兰大教堂前的摆拍照片曝光,引发网友热议。照片中,那英造型时尚,一身黑色长款束腰马甲搭配红唇妆,显瘦又保暖,沉稳又大气,给人一种利落干练之你是唯一的山海,我愿意跋山涉水我的爱不变,绝对不会熄灭,你在它就在。因为你是唯一的山海,我意愿为你跋山涉水,看日出日落,赏花开花谢。我的爱就像火苗,把我的的心燃烧,爱你一生无悔,花前月下,是开弓没有回头箭。我的现代诗(53)愿望美丽的神话源远流长,美好的传说东风浩荡,美妙的旋律奋发向上,美满的生活幸福安康,东方的太阳升起来了!举世瞩目人人敬仰!仿佛看到了北京天安门,天安门上的红太阳!五十六个民族如鲜花般的赏读人生又一秋,生命又一程,美好在路上作者飘逸总觉得时间走的太急,从春风万里,到草木萧索,不知不觉间,秋天已过半。斜倚秋的门楣,静静的思绪涟漪成半山的秋韵。五彩斑斓,绵延逶迤的一川秀色,尽收眼底。天空湛蓝,纤尘不染。推
儿子抑郁症,治疗4个月恢复不错,是否可以上学了?儿子抑郁症,治疗4个月恢复不错,是否可以上学了?抑郁症的本质,是大脑里自动运行的思维程序,这个思维程序是在到了某些刺激点的时候运行,如学生到了学校,看见某老师,进了教室。职工到了工我的孩子患抑郁症,想带着他出去旅游,不知道能不能让他走出来?谢邀请!心病还需心药医!孩子抑郁不是一天两天得的,是日积月累造成的。应该反省自己在平时生活中有没有做事或者处理问题是带枪夹棍,或者简单粗暴从未站在孩子的角度分析或考虑问题。让孩子心买部手机不超过1000元,拿出来用丢人吗?没人在呼你手里的手机是多少钱的,不要去攀比,如人要吃饭,有钱人去高级大酒店,一顿早餐80一300元,而你没能力去攀比只能去街边小吃去吃早饭,不去街边吃要饿肚子,当你吃饱后谁管你吃什为什么一些陕西人吃面条无蒜不欢?北方有句俗语,吃面没吃蒜,等于没吃饭。可见面条和大蒜是最好的搭配,也是一些人喜爱的食物。一方水土养一方人。陕西人栽植大蒜吃大蒜,种植小麦吃面条,是老祖宗留下的生活习惯。生吃大蒜之后为什么小米10s手机拍照会出现中心清晰,边缘模糊的现象?这种现象在摄影界称之为景深。下图是焦距,光圈,距离对景深的影响小米10s的主摄在近拍有明显的边缘虚化证明该镜头景深较浅,浅景深适合拍特写和人像,如下图(只做理解非小米10s拍摄)在有人说,长寿是一场灾难,你是否认同,为什么?我妈上一周终于死了,90岁,卧病在床一年多。一个老人太长寿真的就是一场灾难,对老人来说是灾难,对家人来说更是一场灾难。我知道自己说出这样的话,看起来非常大逆不道。但是照顾一个行动不建议取消外卖,回归健康生活,你怎么看?凡事有利有弊,不能一刀切,不建议取消。非要取消还不如,下定决心整顿下外卖行业,让商家,平台骑手更正规化。1。平台应该提高平台入驻的条件,严格审核商家入驻资格,对于出现违规情况的商家年轻时坚持健身,老了身体会不会更健康?这个问题的答案取决于年轻时怎么健身的,健身强度是否合适。众所众知,对于专业运动员来说,他们只能辉煌几年,然后就会因各种伤痛而不得不退役,究其原因,并不是因为他们从事的运动项目不健康子宫被切除的女人,与正常女人有什么区别,会影响健康吗?子宫切除,大体上同平时好似没有太大影响。实际上身体分泌激素功能明显低了,抵抗力会差些,疾病会多些,性生活会有少少影响,主要来源于心理。如果你放下包袱,就根本没什么影响!激素低,可以有哪些长期不良习惯会伤害肠道健康?说起肠道菌群失调和肥胖的关系,很多人可能会觉得吃惊,怎么肥胖还和肠道菌群有关系啊?是的,肥胖还真的和肠道菌群有着千丝万缕的关系。今天张大夫就来讲一讲这个问题。很多研究都已经表明肥胖联想深陷舆论,你还会认为收购IBM是民族之光吗?从现在看lx当初收购IBM就是进行资产转移的一个局,蒙蔽了上级监管机关,欺骗了广大善良的股民和媒体,他是这些年把国有资产光明正大的公开转移到国外自己名下的第一人,当初有多少人欢呼雀