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

分享一个修改了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
  最后再说一句,感兴趣的朋友可以点赞加关注,你的支持将是我更新动力。

沈梦辰主持湖南卫视小年夜,穿一条白色一字肩长裙,温柔又优雅!沈梦辰的主持风格比较活泼幽默,大家都很喜欢这个大大咧咧的女孩子吧?这不,她主持的湖南卫视小年夜晚会,大家都看了没?小k这次又被沈梦辰的新造型给吸引了,她应该也是一个隐藏的时尚博主吧1973年,广西舞蹈演员自称毛主席女儿,毛主席得知后我想见见她大藤峡水利枢纽工程是国家标志性的水利建设工程,这个项目的投资额度已经达到了30个亿,这对于西江经济的发展和造福流域地区的广大人民群众都带来了极大的好处。而在大藤峡的悬崖壁上,因为有2023年泉州拟增160所5G专递课堂县市级试点校2023年,泉州拟再增加160所5G专递课堂县市级试点校,439个试点班级,届时将有6万名学生受益。泉州探索5G专递课堂新型教学模式云端课堂建桥梁搭起教研共同体打破时空限制,让城乡刘德华的女儿刘向蕙小小年纪身家过亿,心疼母亲为爱躲藏23年文知心录编辑知心录2009年8月,刘德华在香港机场被等待已久的媒体记者们逮了个正着。作为明星被记者抓拍是很正常的事,更别说还是刘德华这样一个天王巨星。可这次的场景和之前完全不同,一甄子丹一家四口罕露面,老婆穿露肩裙像贵妇,女儿身材不输超模妈人的相貌或许相似,但是气质却不尽相同,即使是至亲,也会因为年龄和阅历的不同,呈现不一样的气质,特别是在穿搭上,体现为不同的审美和搭配。在年轻一代身上,可以倒映出老一辈人的影子,但是我的世界春节版本开启,联动刺客伍六七还有新玩法我的世界手游上线了新春联动版本,国产人气高分动画IP刺客伍六七的主角团这一次集体来到了我的世界的世界之中,那么这次的版本会有哪些有趣的内容呢?让我们一起来看看吧。首先必须拿出来说的歧路旅人2全方位实机演示分析!像素回合制有了更多特色玩法随着2023年的进入,想必大家对众多新游早已期待不已,结合新游网上能够找到的资源,老基德打算1月份肝一个系列出来,从各个角度对新游进行细节分析,希望能够帮助大家更好的期待和排查,能国产网游原神登上央视春晚1月14日。播出的央视总台网络春晚上,上海京剧院演员杨扬在节目红妆中演唱了神女劈观唤情片段。本次舞台的设计与原神尘歌壶摆设梨园台榭云翰风致相似,舞台上也出现了原神中角色云堇的剪影。女主播护士服听诊诱惑太大,网友黑丝女仆YYDS我的生活也是头条小小奶瓶在参加完恋综后粉丝大涨,专业日语导师的奶瓶,在和粉丝聊天中,也时不时秀出日语水平。而在平时的直播中,小小奶瓶,解锁新奇开播姿势。跪姿在椅子上,疯狂撩腿,无论王者荣耀意识怎么提升意识怎么练?学会判断游戏局势大家好呀,马上就要过年了,提前祝大家新年快乐。今天小编教大家怎么提升自己的意识1多看小地图多看小地图这个方法是最简单并且也是游戏中最重要的办法,因为多看小地图可以让你直到敌方英雄的豪门梦碎!顶级女明星都抓不住富豪的心,被劈腿了泰国的开年瓜,有点劲爆哦!一姐和她的富商男友分手了。稍微了解泰娱的,都对这女明星不陌生吧?帕德容琶砂楚,Aump爱的羁绊我亲爱的小冤家这两部作品,让她的红遍整个东南亚。最绝的是,堪
泰山区重点项目建设如火如荼一年之计在于春。春节刚过,正是万物准备迸发新生机的时候,泰山区开局即决战,起步即冲刺,重点项目建设进行得如火如荼。位于泰山经济开发区的国家先进印染技术创新中心项目现场,中心负责人介雷诺与日产联盟重组即将达成,未来或将重点关注中美及新兴市场1月30日,日产汽车宣布,经过与雷诺集团数月的建设性讨论,双方已达成最新合作关系的重要里程碑。结合雷诺所发布的相关声明来看,未来,在董事会的批准下,双方将以加强联盟的联系为目标,并总投资4523。08亿元!天津这些重点推介项目集中签约!2月1日上午,天津举行重点推介项目首期集中签约仪式。记者获悉,首期集中签约项目共38个总投资4523。08亿元。此次集中签约项目支撑强领域广理念新。从签约项目总投资看,百亿元以上项十二指肠溃疡,多因肝郁脾虚,中医名方健脾益气,疏肝解郁你有没有胃胀,胸闷,嗳气,胃里反酸的现象,每次上厕所的时候,大便不成型,还容易黏在马桶上。去医院检查,发现是十二指肠球部溃疡。十二指肠和胃挨着,位于胃和空肠之间。十二指肠溃疡是胃疼老中医诊断宫寒主要看这几点望经血颜色偏黯黑色白带色白清稀量多,面色黯黑或苍白无华,舌色黯淡,舌苔白而且水滑。闻白带有腥臭味。问痛经黄褐斑性欲不振月经延期甚至闭经腰膝酸冷四肢不温。触小腹温度较低。有些女性先天我心中的中医能否用一句话概括你对中医的评价中国中医博大精深,西医治标,中医治本,老祖宗留下来的东西,外国人都觊觎,而我们很多人却是持怀疑态度,这得让老祖宗得多伤心中医源于生活,生活的每个环节,中医保护了我们五千年?这里不探讨我们上下到底几千年问题,只按约定俗成的说法来谈!我们几千年来确实一直用的中医保护,保护的结果如何?有研究说,历史上中国人平均年龄在4050岁之间,这和民间流传的人活七十古总是咳白痰,遇冷天气加重,分享一个好用中成药,温化寒痰很多朋友总是有白痰,有时咳嗽,有时也不咳嗽,白痰总在嗓子里面堵着,痰液比较稀薄,怎么办呢?今天马医生给大家分享一个中成药,助大家解决这个问题。首先,有的人说,中医治痰要先治脾,因为痛风患者如何正确吃水果近些年,痛风已经日渐成为危害患者日常健康的疾病之一,而目前除了药物对这种疾病的治疗之外,痛风患者日常的饮食习惯问题也同样是不容忽视的,比如减少高油高糖高嘌呤食物及酒精等。水果是公认帝王心术为何汉武帝手下的能人那么多?背后的秘密究竟是什么?汉武帝,被很多人称作千古一帝,他为什么这么厉害,有人说是他手下的能人太多了,这种井喷式的人才,让他不成为千古一帝都很难。但我想说的是,人才每个时代都有很多,并不是汉武帝时期,就比其古代帝王都有哪些传奇身世汉高祖刘邦根据司马迁的史记记载其先刘媪尝息大泽之陂,梦与神遇。是时雷电晦冥,太公往视,则见蛟龙於其上。已而有身,遂产高祖。大意就是说刘邦他妈在野外睡着了,梦里遇到了神仙,而他爸过去