分享一个修改了xml文件再也不用重启的项目mybatisxm
自我18年使用Mybaits以来,开发环境中如果修改了xml文件后,只有重启项目才能生效,如果小项目重启还好,但是对于一个重启需要十几分钟的大型项目来说,这就非常耗时了。开发人员因为修改了xml文件少量内容,比如添加一个逗号、查询增加一个字段或者修改一个bug等,就需要重启整个项目,这就非常痛苦了。
所以在这里给大家推荐一个实现了Mybatisxml文件热加载的项目,mybatisxmlreloadspringbootstarter。它能够帮助我们在SpringBootMybatis的开发环境中修改xml后,不需要重启项目就能让修改过后xml文件立即生效,实现热加载功能。这里给出项目地址:https:github。comwayn111mybatisxmlreloadspringbootstarter欢迎大家关注,点个star
ps:mybatisxmlreloadspringbootstarter目前3。0。3。m1版本实现了xml文件修改已有内容,比如修改sql语句、添加查询字段、添加查询条件等,可以实现热加载功能。但是对于xml文件添加insertupdatedeleteselect标签等内容后,是无法实现热加载的。众所周知,在Idea环境进行Java开发,在方法内修改方法内容是可以热加载的。但是添加新方法、添加方法参数,修改方法参数,修改方法返回值等都是无法直接热加载的。一、mybatisxmlreloadspringbootstarter使用
mybatisxmlreloadspringbootstarter原理:修改xml文件的加载逻辑。在普通的mybatisspring项目中,默认只会加载项目编译过后的xml文件,也就是target目录下的xml文件。但是在mybatisxmlreloadspringbootstarter中,修改了这一点,它会加载项目resources目录下的xml文件,这样用户对于resources目录下xml文件的修改操作是可以立即触发热加载的。通过io。methvin。directorywatcher项目来监听xml文件的修改操作,它底层是通过java。nio的WatchService来实现,当我们监听了整个resources目录后,xml文件的修改会立马触发MODIFY事件。通过mybatisspring项目原生的xmlMapperBuilder。parse()方法重新加载解析修改过后的xml文件来保证项目对于Mybatis的兼容性处理。二、技术原理
mybatisxmlreloadspringbootstarter代码结构如下:
核心代码在MybatisXmlReload类中,执行逻辑:通过项目初始化时传入MybatisXmlReloadPropertiesprop,ListsqlSessionFactories参数,获取mybatisxmlreloadspringbootstarter的配置信息,以及项目中的数据源配置是否启动以及xml路径的配置类privateMybatisXmlReloadPropertiesprop;获取项目中初始化完成的SqlSessionFactory列表,对多数据源进行处理privateListSqlSessionFactorysqlSessionFactories;publicMybatisXmlReload(MybatisXmlReloadPropertiesprop,ListSqlSessionFactorysqlSessionFactories){this。propprop;this。sqlSessionFactoriessqlSessionFactories;}解析配置文件指定的xml路径,获取xml文件在target目录下的位置解析项目所有xml路径,获取xml文件在target目录中的位置ListResourcemapperLocationsTmpStream。of(Optional。of(prop。getMapperLocations())。orElse(newString〔0〕))。flatMap(locationStream。of(getResources(patternResolver,location)))。toList();根据xml文件在target目录下的位置,进行路径替换找到xml文件所在resources目录下的位置根据xml文件在target目录下的位置,进行路径替换找到该xml文件在resources目录下的位置for(ResourcemapperLocation:mapperLocationsTmp){mapperLocations。add(mapperLocation);StringabsolutePathmapperLocation。getFile()。getAbsolutePath();FiletmpFilenewFile(absolutePath。replace(CLASSPATHTARGET,MAVENRESOURCES));if(tmpFile。exists()){locationPatternSet。add(Path。of(tmpFile。getParent()));FileSystemResourcefileSystemResourcenewFileSystemResource(tmpFile);mapperLocations。add(fileSystemResource);}}对resources目录的xml文件的修改操作进行监听对resources目录的xml文件修改进行监听ListPathrootPathsnewArrayList();rootPaths。addAll(locationPatternSet);DirectoryWatcherwatcherDirectoryWatcher。builder()。paths(rootPaths)orusepaths(directoriesToWatch)。listener(event{switch(event。eventType()){caseCREATE:filecreatedbreak;caseMODIFY:filemodifiedPathmodifyPathevent。path();StringabsolutePathmodifyPath。toFile()。getAbsolutePath();logger。info(mybatisxmlfilehaschanged:modifyPath);执行热加载逻辑。。。break;caseDELETE:filedeletedbreak;}})。build();ThreadFactorythreadFactoryr{ThreadthreadnewThread(r);thread。setName(xmlreload);thread。setDaemon(true);returnthread;};watcher。watchAsync(newScheduledThreadPoolExecutor(1,threadFactory));对多个数据源进行遍历,判断修改过的xml文件属于那个数据源对多个数据源进行遍历,判断修改过的xml文件属于那个数据源for(SqlSessionFactorysqlSessionFactory:sqlSessionFactories){。。。}根据Configuration对象获取对应的标签属性根据Configuration对象获取对应的标签属性ConfigurationtargetConfigurationsqlSessionFactory。getConfiguration();Classlt;?tClasstargetConfiguration。getClass(),aClasstargetConfiguration。getClass();if(targetConfiguration。getClass()。getSimpleName()。equals(MybatisConfiguration)){aClassConfiguration。class;}SetStringloadedResources(SetString)getFieldValue(targetConfiguration,aClass,loadedResources);loadedResources。clear();MapString,ResultMapresultMaps(MapString,ResultMap)getFieldValue(targetConfiguration,tClass,resultMaps);MapString,XNodesqlFragmentsMaps(MapString,XNode)getFieldValue(targetConfiguration,tClass,sqlFragments);MapString,MappedStatementmappedStatementMaps(MapString,MappedStatement)getFieldValue(targetConfiguration,tClass,mappedStatements);遍历resources目录下xml文件列表遍历resources目录下xml文件列表for(ResourcemapperLocation:mapperLocations){。。。}判断是否是被修改过的xml文件,否则跳过判断是否是被修改过的xml文件,否则跳过if(!absolutePath。equals(mapperLocation。getFile()。getAbsolutePath())){continue;}解析xml文件,获取修改后的xml文件标签对应的resultMapssqlFragmentsMapsmappedStatementMaps的属性并执行替换逻辑,并且兼容mybatisplus的替换逻辑重新解析xml文件,替换Configuration对象的相对应属性XPathParserparsernewXPathParser(mapperLocation。getInputStream(),true,targetConfiguration。getVariables(),newXMLMapperEntityResolver());XNodemapperXnodeparser。evalNode(mapper);StringnamespacemapperXnode。getStringAttribute(namespace);ListXNoderesultMapNodesmapperXnode。evalNodes(mapperresultMap);for(XNodexNode:resultMapNodes){StringidxNode。getStringAttribute(id,xNode。getValueBasedIdentifier());resultMaps。remove(namespace。id);}ListXNodesqlNodesmapperXnode。evalNodes(mappersql);for(XNodesqlNode:sqlNodes){StringidsqlNode。getStringAttribute(id,sqlNode。getValueBasedIdentifier());sqlFragmentsMaps。remove(namespace。id);}ListXNodemsNodesmapperXnode。evalNodes(selectinsertupdatedelete);for(XNodemsNode:msNodes){StringidmsNode。getStringAttribute(id,msNode。getValueBasedIdentifier());mappedStatementMaps。remove(namespace。id);}重新加载和解析被修改的xml文件9。重新加载和解析被修改的xml文件try{XMLMapperBuilderxmlMapperBuildernewXMLMapperBuilder(mapperLocation。getInputStream(),targetConfiguration,mapperLocation。toString(),targetConfiguration。getSqlFragments());xmlMapperBuilder。parse();}catch(Exceptione){logger。error(e。getMessage(),e);}三、安装方式在SpringBoot3。0中,mybatisxmlreloadspringbootstarter在Maven项目提供坐标地址如下:dependencygroupIdcom。wayngroupIdmybatisxmlreloadspringbootstarterartifactIdversion3。0。3。m1versiondependency在SpringBoot2。0Maven项目提供坐标地址如下:dependencygroupIdcom。wayngroupIdmybatisxmlreloadspringbootstarterartifactIdversion2。0。1。m1versiondependency四、使用配置
mybatisxmlreloadspringbootstarter目前只有两个配置属性。mybatisxmlreload。enabled默认是false,也就是不启用xml文件的热加载功能,想要开启的话通过在项目配置文件中设置mybatisxmlreload。enabled为true。还有一个配置属性是mybatisxmlreload。mapperlocations,执行热加载的xml文件路径,这个属性需要手动填写,跟项目中的mybatis。mapperlocations保持一直即可。具体配置如下:mybatisxml文件热加载配置mybatisxmlreload:是否开启xml热更新,true开启,false不开启,默认为falseenabled:truexml文件路径,可以填写多个,逗号分隔。eg:classpath:mapperMapper。xml,classpath:otherMapper。xmlmapperlocations:classpath:mapperMapper。xml五、最后
欢迎大家使用mybatisxmlreloadspringbootstarter,这个项目我开源的的,使用中遇到问题可以提交issue。提交的问题我都会一一查看并回复。再附项目地址:https:github。comwayn111mybatisxmlreloadspringbootstarter
最后再说一句,感兴趣的朋友可以点赞加关注,你的支持将是我更新动力。
深圳5大樱花观赏地春天和樱花有个约会樱花烂漫几多时?眼下正到了樱花的最佳赏花期,深圳最街坊为你收集了樱花地图,不出深圳,就能和樱花来一场浪漫约会!小三洲塘片区樱花林这里种植有中国红广州樱寒绯樱等不同品种樱花水库离大华
烟花三月下扬州在我国的古典诗词中,与地名有关的诗词可有很多,很多城市历史悠久,文化底蕴深厚,深受广大诗词名家青睐。有这样一座城市,它地处江南,千百年来,无数诗词名家在此写下了数不胜数的名句。二十
福建20烟火汀州自多彩,何必长汀比凤凰云游风物之旅前言游人提到长汀,言必比凤凰,就是因为路易艾黎的那句话,中国最美的山城有两座,一座是湖南的凤凰,一座是福建的长汀。长汀人自己听着都有点烦了,堂堂的唐朝福建五州之一,客家
650平方公里,西南第三城昆明建成区测量春城昆明,云南省省会,滇中城市群中心城市,是云贵高原第一城,西南第三大城市,国务院批复确定的中国西部地区重要的中心城市之一。昆明市昆明市辖区面积2。1万平方公里,下辖7区(西山区呈
群鸟戏水把春报!济南黄河畔有个水鸟乐园3月1日,记者在位于济南黄河北岸的鹊山水库沉砂池看到,成群的水鸟在滩涂湿地栖息觅食,不时结伴在水面游弋,时而又梳理羽毛,有的在蓝天下飞翔,享受着初春的暖阳,一派怡然自得生机勃勃的景
尼泊尔警方诬陷我这期和大家分享一下尼泊尔jing方诬陷我的事。尼泊尔jing方诬陷我也就是第三次kaskijing局抓的我,上次说到博卡拉旅游jing察局第二次放了我,我刚走出旅游jing察局的大
3月起又有多条国际航线恢复!成都飞胡志明市普吉岛更方便了3月1日,记者从中国国际航空(简称国航)获悉,2023年4月11日起,国航将恢复成都至普吉岛的国际航班,航班号为CA4134,去程计划0955从成都天府国际机场起飞,当地时间125
五一这样操作可以连休9天!快看看放假安排吧!今年五一4月29日至5月3日放假共5天如果还嫌5天不够过瘾怎么办?你可以在5月4日到5月6日请假3天加上5月7日周日就可以形成9天的假期这么长的假期一定要先计划好去哪里玩。这是笔者
盘点湖北荆州古城的33个人文景观,个个文化底蕴深厚早在上世纪八十年代初,湖北江陵县(现荆州区)就被评为国家级历史文化名城,荆州古城墙更被誉为南方不可多得的完璧。荆州古城内外到底有多少人文景观?小编进行了认真梳理,发现人文景观数量竟
走两步,没病走两步姚主席应该直面全部质疑昨天深夜,新疆男篮发布公告,正式退出CBA,除了认为中国篮协之前认定其注册违规侵害了俱乐部的合法权益外,还将矛头指向了周琦及其经纪团队,中国篮协,甚至中国篮协主席姚明。在之前的严正
中超土洋教头88!2队仍无主帅,海港坑苦嵩山龙门,升班马或解散时间过得很快,转眼间3月已经到来,如果本赛季中超联赛的赛程能够按照足协的计划进行,那么现在距离2023中超联赛的开幕就只剩下1个多月的时间了。而目前中超18队中有16支,已经确定了