mybatis xml 文件热加载实现

简介: mybatis xml 文件热加载实现

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;
    }
}



























































































































































         
相关文章
|
1月前
|
XML 前端开发 Java
讲解SSM的xml文件
本文详细介绍了SSM框架中的xml配置文件,包括springMVC.xml和applicationContext.xml,涉及组件扫描、数据源配置、事务管理、MyBatis集成以及Spring MVC的视图解析器配置。
59 1
|
3月前
|
XML Java 数据格式
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
这篇文章是Spring5框架的实战教程,主要介绍了如何在Spring的IOC容器中通过XML配置方式使用外部属性文件来管理Bean,特别是数据库连接池的配置。文章详细讲解了创建属性文件、引入属性文件到Spring配置、以及如何使用属性占位符来引用属性文件中的值。
Spring5入门到实战------7、IOC容器-Bean管理XML方式(外部属性文件)
|
12天前
|
Java Maven
maven项目的pom.xml文件常用标签使用介绍
第四届人文,智慧教育与服务管理国际学术会议(HWESM 2025) 2025 4th International Conference on Humanities, Wisdom Education and Service Management
64 8
|
17天前
|
SQL 缓存 Java
MyBatis如何关闭一级缓存(分注解和xml两种方式)
MyBatis如何关闭一级缓存(分注解和xml两种方式)
49 5
|
1月前
|
XML JavaScript Java
java与XML文件的读写
java与XML文件的读写
26 3
|
1月前
|
XML 存储 缓存
C#使用XML文件的详解及示例
C#使用XML文件的详解及示例
95 0
|
1月前
|
XML 存储 Web App开发
查看 XML 文件
查看 XML 文件
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
45 1
|
1月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
112 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
54 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块