1试了jrebel 放弃了
2试了Dev tool放弃了
3下面一招解决mybatis xml 文件热加载实现
import org.apache.ibatis.builder.xml.XMLMapperBuilder; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.SqlSessionFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.stereotype.Component; import java.io.IOException; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @Component public class XMLMapperReloader implements ApplicationContextAware { private ConfigurableApplicationContext context = null; private HashMap<String, Long> fileMapping = new HashMap<String, Long>(); private Scanner scanner = null; private String packageSearchPath="classpath:mapper/*.xml"; private ScheduledExecutorService service = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = (ConfigurableApplicationContext) applicationContext; } public XMLMapperReloader(){ service = Executors.newScheduledThreadPool(1); service.scheduleAtFixedRate(new Task(), 5, 5, TimeUnit.SECONDS); } class Task implements Runnable { @Override public void run() { try { scanner = new Scanner(); scanner.refreshMapper(); } catch (Exception e) { e.printStackTrace(); } } } @SuppressWarnings({ "rawtypes" }) class Scanner { private Resource[] mapperLocations; public void refreshMapper() { try { SqlSessionFactory factory = context.getBean(SqlSessionFactory.class); Configuration configuration = factory.getConfiguration(); // step.1 扫描文件 try { this.scanMapperXml(); } catch (IOException e) { return; } // step.2 判断是否有文件发生了变化 if (this.isChanged()) { System.out.println("==============检测到mapper有改变, 开始刷新...==============="); // 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(); } catch (IOException e) { continue; } } System.out.println("==============mapper刷新完毕==============="); } } catch (Exception e) { e.printStackTrace(); } } private void scanMapperXml() throws IOException { this.mapperLocations = new PathMatchingResourcePatternResolver().getResources(packageSearchPath); } 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"); } 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(); } 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(); } 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; } } public String getPackageSearchPath() { return packageSearchPath; } public void setPackageSearchPath(String packageSearchPath) { this.packageSearchPath = packageSearchPath; } }