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

我们公司的项目比较大,启动起来特别慢,基本得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的时候,调用一下,或者我在开发某个接口时,在最开始调用一下,接口开发好后,删掉

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值