mybatis修改xml文件后,不需要重启项目

    xiaoxiao2022-07-12  121

    我们公司的项目比较大,启动起来特别慢,基本得5分钟左右,改其他东西还好,但是改sql时太痛苦了,改完一个,重启,等待,登录,找到刚才的模块,测试,擦,少考虑一个东西,还得改,重启,等待。。。。。。 然后就在网上搜一下有没有不用重启的办法,还真有,https://mp.csdn.net/mdeditor# 我是基于这个修改一个开发环境比较适用的版本 首先说一下这篇文章里的配置 配置我是放在spring-servlet.xml中,sqlSessionFactoryPay 取的值是spring-context.xml中mybatis 配置的bean 的id 然后把sqlSessionFactory,packageSearchPath 改成静态的,在把该类改成单例的,方便调用

    刷新的类

    package com.kyee.framework.config; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.List; 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.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; public class RefreshMapperCache { private Log log = LogFactory.getLog(RefreshMapperCache.class); private static SqlSessionFactory sqlSessionFactory; private Resource[] mapperLocations; private static String packageSearchPath; private HashMap<String, Long> fileMapping = new HashMap<String, Long>();// 记录文件是否变化 //记录发生改变的xml文件名称 private List<String> changeResourceNameList = new ArrayList<>(); private static RefreshMapperCache singletonHungary = new RefreshMapperCache(); public static RefreshMapperCache getInstance() { return singletonHungary; } public RefreshMapperCache(){ } public void refreshMapper() { try { Configuration configuration = this.sqlSessionFactory.getConfiguration(); // step.1 扫描文件 try { this.scanMapperXml(); } catch (IOException e) { log.error("packageSearchPath扫描包路径配置错误"); return; } // System.out.println("==============刷新前mapper中的内容 start==============="); // //获取xml中的每个语句的名称即 id = "findUserById"; // for (String name : configuration.getMappedStatementNames()) { // System.out.println(name); // } // System.out.println("==============刷新前mapper中的内容 end==============="); //清空被修改过后的文件名称,确保该集合是空的 changeResourceNameList.clear(); // step.2 判断是否有文件发生了变化 if (this.isChanged()) { // step.2.1 清理 this.removeConfig(configuration); // step.2.2 重新加载 for (Resource configLocation : mapperLocations) { try { //匹配被修改过的mapper文件,如果存在,则重新加载 //如果想要重新加载全部mapper,可以不匹配 if(changeResourceNameList.contains(configLocation.getFilename())){ XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configLocation.getInputStream(), configuration, configLocation.toString(), configuration.getSqlFragments()); xmlMapperBuilder.parse(); System.out.println("mapper文件[" + configLocation.getFilename() + "]缓存加载成功"); } } catch (IOException e) { System.out.println("mapper文件[" + configLocation.getFilename() + "]不存在或内容格式不对"); continue; } } //清空被修改过后的文件名称 changeResourceNameList.clear(); } // System.out.println("--------------------------刷新后mapper中的内容 start--------------------------"); // for (String name : configuration.getMappedStatementNames()) { // System.out.println(name); // } // System.out.println("--------------------------刷新后mapper中的内容 end--------------------------"); } catch (Exception e) { System.out.println("****************刷新缓存异常: "+e.getMessage()); } } 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 * @return * @throws IOException */ private boolean isChanged() throws IOException { boolean flag = false; System.out.println("***************************获取文件名 开始************************************"); for (Resource resource : mapperLocations) { String resourceName = resource.getFilename(); System.out.println("resourceName == " + resourceName+", path = "+resource.getURL().getPath()); 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){ System.out.println(" 新增了:==="+ resourceName); } if(modifyFlag){ System.out.println(" 修改了:==="+ resourceName); } // 新增或是修改时,存储文件 if(addFlag || modifyFlag) { fileMapping.put(resourceName, Long.valueOf(lastFrame));// 文件内容帧值 flag = true; changeResourceNameList.add(resourceName); } } System.out.println("***************************获取文件名 结束************************************"); return flag; } }

    调用的地方

    RefreshMapperCache.getInstance().refreshMapper();

    这样我就可以在需要的重新加载xml的时候,调用一下,或者我在开发某个接口时,在最开始调用一下,接口开发好后,删掉

    最新回复(0)