zoukankan      html  css  js  c++  java
  • MyBatis热部署

    代码

    import java.io.IOException;
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.Timer;
    import java.util.TimerTask;
    
    import org.apache.ibatis.builder.xml.XMLMapperBuilder;
    import org.apache.ibatis.executor.ErrorContext;
    import org.apache.ibatis.session.Configuration;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.InitializingBean;
    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.core.io.support.ResourcePatternResolver;
    import org.springframework.stereotype.Repository;
    
    /**
     * 定时扫描并动态加载mybatis的SQL配置文件,刷新sql mapper cache,可以在修改xml后不用重启tomcat也能生效
     * 
     * 扫描参数:<br/>
     * 1.RELOAD_INTERVAL:扫描时间间隔=3s<br/>
     * 2.XML_RESOURCE_PATTERN:当前CLASSPATH下xml通配符<br/>
     * 3.SESSION_FACTORY_BEAN_NAME:数据源session factory名称<br/>
     * 备注:本类在开发环境下使用,正式发布后注释掉applicationContext.xml中id=MyBatisDynamicLoader的bean
     * 
     * @author MF
     * @version 1.0
     */
    @Repository("XMLMapperLoader")
    public class XMLMapperLoader implements InitializingBean, ApplicationContextAware {
    	// 扫描时间间隔
    	private static final long RELOAD_INTERVAL = 3000;
    
    	private final HashMap<String, String> mappers = new HashMap<String, String>();
    	private volatile ConfigurableApplicationContext context = null;
    	private volatile Scanner scanner = null;
    
    	@Override
    	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    		this.context = (ConfigurableApplicationContext) applicationContext;
    	}
    
    	@Override
    	public void afterPropertiesSet() throws Exception {
    		try {
    			scanner = new Scanner();
    			new Timer(true).schedule(new TimerTask() {
    				public void run() {
    					try {
    						if (scanner.isChanged()) {
    							scanner.reloadXML();
    						}
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    			}, 5 * 1000, RELOAD_INTERVAL);
    		} catch (Exception e1) {
    			e1.printStackTrace();
    		}
    	}
    
    	class Scanner {
    		private static final String XML_RESOURCE_PATTERN =
    				ResourcePatternResolver.CLASSPATH_URL_PREFIX + "mapper/*/*.xml";
    		private static final String SESSION_FACTORY_BEAN_NAME = "sqlSessionFactory";
    
    		private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    
    		public Scanner() throws IOException {
    			Resource[] resources = findResource();
    			if (resources != null) {
    				for (Resource resource : resources) {
    					String key = resource.getURI().toString();
    					String value = getMd(resource);
    					mappers.put(key, value);
    				}
    			}
    		}
    
    		public void reloadXML() throws Exception {
    			// 如果是单数据源用这个
    			// SqlSessionFactory factory = context.getBean(SqlSessionFactory.class);
    			/* 这里指定数据源,多数据源环境使用 */
    			System.out.println("========== Reload SQL Cache on [" + SESSION_FACTORY_BEAN_NAME + "] ==========");
    			SqlSessionFactory factory = (SqlSessionFactory) context.getBean(SESSION_FACTORY_BEAN_NAME);
    			Configuration configuration = factory.getConfiguration();
    			removeConfig(configuration);
    			for (Resource resource : findResource()) {
    				System.out.println(resource.getFilename());
    				try {
    					XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(), configuration,
    							resource.toString(), configuration.getSqlFragments());
    					xmlMapperBuilder.parse();
    				} finally {
    					ErrorContext.instance().reset();
    				}
    			}
    			System.out.println("========== Reload end ==========");
    		}
    
    		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) field.get(configuration)).clear();
    		}
    
    		@SuppressWarnings("rawtypes")
    		private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
    			Field field = classConfig.getDeclaredField(fieldName);
    			field.setAccessible(true);
    			((Set) field.get(configuration)).clear();
    		}
    
    		public boolean isChanged() throws IOException {
    			boolean isChanged = false;
    			for (Resource resource : findResource()) {
    				String key = resource.getURI().toString();
    				String value = getMd(resource);
    				if (!value.equals(mappers.get(key))) {
    					isChanged = true;
    					mappers.put(key, value);
    				}
    			}
    			return isChanged;
    		}
    
    		private Resource[] findResource() throws IOException {
    			return resourcePatternResolver.getResources(XML_RESOURCE_PATTERN);
    		}
    
    		private String getMd(Resource resource) throws IOException {
    			return new StringBuilder()
    					.append(resource.contentLength())
    					.append("-")
    					.append(resource.lastModified())
    					.toString();
    		}
    	}
    }
    

    Spring加载方式

    加载方式:在Spring XML文件中加入:(发布生产时要注释掉,不启动)
    <!-- MyBatis 热加载,修改无需重新部署web容器的bean -->
    <bean id ="MyBatisDynamicLoader" class= "com.xxx.XMLMapperLoader"/>
    
  • 相关阅读:
    python学习笔记(二十):异常处理
    python学习笔记(十九)面向对象编程,类
    发邮件
    网络编程
    python学习笔记(十八)python操作excel
    BZOJ 3413 匹配 (后缀自动机+线段树合并)
    BZOJ 2555 SubString (后缀自动机+LCT)
    BZOJ 1396 识别子串 (后缀自动机+线段树)
    BZOJ 2780 Sevenk Love Oimaster (后缀自动机+树状数组+dfs序+离线)
    BZOJ 3998 [TJOI2015]弦论 (后缀自动机)
  • 原文地址:https://www.cnblogs.com/okokabcd/p/8779551.html
Copyright © 2011-2022 走看看