热部署

1、将springloaded-1.2.5.RELEASE.jar(http://pan.baidu.com/s/1o7oRq1k)放在tomcat的bin目录下
2、修改bin目录下的catalina.bat,在第一行加上下面这一句,注意路径可能需要修改一下:
set JAVA_OPTS=-javaagent:E:apache-tomcat-7.0.55inspringloaded-1.2.5.RELEASE.jar -noverify
如此以来,所有的class文件更新都会实时反馈,但是新增的类文件的注解并不能生效

如果是想在eclipse的tomcat中使用,则在run configruation的相应tomcat的arguments的VM arguments中另起一行添加一个变量:-Djavaagent:D:softDevelopSoft oolsjarspringloaded-1.2.5.RELEASE.jar -noverify  即可

注意eclipse中的tomcat默认是代码修改就会重启的,这和我们的热部署是冲突的,所以我们要禁用tomcat的自动重启:

去掉对号:

 

server.xml的reloadable设为false

3、对于mybatis的xml,暂时用手动来触发更新,可以参考SysUtilsController.java中的refreshMappers方法,手动来触发该方法就会重新加载所有spring配置文件中指定路径的xml

【SysUtilsController】

 1 /**
 2  * 
 3  * @ClassName: SysUtilsController
 4  * @Description: TODO
 5  * @author: liuyx 
 6  * @date: 2016年1月5日下午5:43:52
 7  */
 8 @Controller
 9 @RequestMapping("/sysUtils")
10 public class SysUtilsController extends BaseController{
11     // 日志记录器
12     private final Logger logger = Logger.getLogger(this.getClass());
13 
14     /**
15      * 
16      * @Title: refreshMappers
17      * @author:liuyx 
18      * @date:2015年12月30日下午6:39:09
19      * @Description: 重新加载所有mapper xml文件
20      * @param request
21      * @return
22      */
23     @RequestMapping("/refreshMappers")
24     @ResponseBody
25     public RetObj refreshMappers(HttpServletRequest request) {
26         MybatisMapperLoadUtil mapperUtil = (MybatisMapperLoadUtil)ComponentFactory.getBean(MybatisMapperLoadUtil.class);
27         try {
28             mapperUtil.getScanner().reloadXML();
29         } catch (Exception e) {
30             // TODO Auto-generated catch block
31             e.printStackTrace();
32             logger.error(e);
33             return new RetObj(false,request);
34         }
35         return new RetObj(true,request);
36     }
37     
38 }

【MybatisMapperLoadUtil】① (这个是根据 XML_RESOURCE_PATTERN 所写的路径扫描所有mapper xml)

  1 import java.io.IOException;
  2 import java.lang.reflect.Field;
  3 import java.util.HashMap;
  4 import java.util.Map;
  5 import java.util.Set;
  6 
  7 import org.apache.ibatis.builder.xml.XMLMapperBuilder;
  8 import org.apache.ibatis.executor.ErrorContext;
  9 import org.apache.ibatis.session.Configuration;
 10 import org.apache.ibatis.session.SqlSessionFactory;
 11 import org.apache.log4j.Logger;
 12 import org.springframework.beans.BeansException;
 13 import org.springframework.beans.factory.InitializingBean;
 14 import org.springframework.context.ApplicationContext;
 15 import org.springframework.context.ApplicationContextAware;
 16 import org.springframework.context.ConfigurableApplicationContext;
 17 import org.springframework.core.io.Resource;
 18 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 19 import org.springframework.core.io.support.ResourcePatternResolver;
 20 
 21 /**
 22  * 用于重新加载Mapper的工具
 23  */
 24 public class MybatisMapperLoadUtil implements InitializingBean, ApplicationContextAware {
 25     // 日志记录器
 26         private final Logger logger = Logger.getLogger(this.getClass());
 27     private final HashMap<String, String> mappers = new HashMap<String, String>();
 28     private volatile ConfigurableApplicationContext context = null;
 29     private volatile Scanner scanner = null;
 30 
 31     @Override
 32     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 33         this.context = (ConfigurableApplicationContext) applicationContext;
 34     }
 35 
 36     @Override
 37     public void afterPropertiesSet() throws Exception {
 38         setScanner(new Scanner());
 39         /*try {
 40             
 41             new Timer(true).schedule(new TimerTask() {
 42                 public void run() {
 43                     try {
 44                         if("off".equals(ConfigService.getConfigRealTime(ConfigService.DYNAMIC_LOAD_MYBATIS_XML_SWITCH))) {
 45                             
 46                         }else {
 47                             if (scanner.isChanged()) {
 48                                 System.out.println("load mapper.xml");
 49                                 scanner.reloadXML();
 50                             }
 51                         }
 52 
 53                     } catch (Exception e) {
 54                         e.printStackTrace();
 55                     }
 56                 }
 57             }, 10 * 1000, 5 * 1000);
 58         } catch (Exception e1) {
 59             e1.printStackTrace();
 60         }*/
 61     }
 62 
 63     public Scanner getScanner() {
 64         return scanner;
 65     }
 66 
 67     public void setScanner(Scanner scanner) {
 68         this.scanner = scanner;
 69     }
 70 
 71     @SuppressWarnings("unchecked")
 72     public
 73     class Scanner {
 74         //此处应调整为可配置
 75         private static final String XML_RESOURCE_PATTERN = "com/sdyy/**/model/*.xml";//ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "**/*Mapper.xml";
 76         private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
 77         public Scanner() throws IOException {
 78             Resource[] resources = findResource();
 79             if (resources != null) {
 80                 for (Resource resource : resources) {
 81                     String key = resource.getURI().toString();
 82                     String value = getMd(resource);
 83                     mappers.put(key, value);
 84                 }
 85             }
 86         }
 87         public void reloadXML() throws Exception {
 88             SqlSessionFactory factory = context.getBean(SqlSessionFactory.class);
 89             Configuration configuration = factory.getConfiguration();
 90             removeConfig(configuration);
 91             for (Resource resource : findResource()) {
 92                 try {
 93                     XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(), configuration, resource.toString(), configuration.getSqlFragments());
 94                     xmlMapperBuilder.parse();
 95                 } finally {
 96                     ErrorContext.instance().reset();
 97                 }
 98             }
 99         }
100         private void removeConfig(Configuration configuration) throws Exception {
101             Class<?> classConfig = configuration.getClass();
102             clearMap(classConfig, configuration, "mappedStatements");
103             clearMap(classConfig, configuration, "caches");
104             clearMap(classConfig, configuration, "resultMaps");
105             clearMap(classConfig, configuration, "parameterMaps");
106             clearMap(classConfig, configuration, "keyGenerators");
107             clearMap(classConfig, configuration, "sqlFragments");
108             clearSet(classConfig, configuration, "loadedResources");
109         }
110         private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
111             Field field = classConfig.getDeclaredField(fieldName);
112             field.setAccessible(true);
113             ((Map) field.get(configuration)).clear();
114         }
115         private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
116             Field field = classConfig.getDeclaredField(fieldName);
117             field.setAccessible(true);
118             ((Set) field.get(configuration)).clear();
119         }
120         public boolean isChanged() throws IOException {
121             boolean isChanged = false;
122             for (Resource resource : findResource()) {
123                 String key = resource.getURI().toString();
124                 String value = getMd(resource);
125                 if (!value.equals(mappers.get(key))) {
126                     isChanged = true;
127                     mappers.put(key, value);
128                 }
129             }
130             return isChanged;
131         }
132         private Resource[] findResource() throws IOException {
133             return resourcePatternResolver.getResources(XML_RESOURCE_PATTERN);
134         }
135         private String getMd(Resource resource) throws IOException {
136             return new StringBuilder().append(resource.contentLength()).append("-").append(resource.lastModified()).toString();
137         }
138     }
139 }

【MybatisMapperLoadUtil】② (这个是根据 mybatis-config.xml所写的所有mappers的路径更新xml)

  1 import java.io.IOException;
  2 import java.io.InputStream;
  3 import java.lang.reflect.Field;
  4 import java.util.Collection;
  5 import java.util.HashMap;
  6 import java.util.Map;
  7 import java.util.Set;
  8 
  9 import org.apache.ibatis.binding.MapperRegistry;
 10 import org.apache.ibatis.builder.xml.XMLConfigBuilder;
 11 import org.apache.ibatis.builder.xml.XMLMapperBuilder;
 12 import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
 13 import org.apache.ibatis.exceptions.ExceptionFactory;
 14 import org.apache.ibatis.executor.ErrorContext;
 15 import org.apache.ibatis.io.Resources;
 16 import org.apache.ibatis.mapping.MappedStatement;
 17 import org.apache.ibatis.parsing.XNode;
 18 import org.apache.ibatis.parsing.XPathParser;
 19 import org.apache.ibatis.session.Configuration;
 20 import org.apache.ibatis.session.SqlSessionFactory;
 21 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
 22 import org.apache.log4j.Logger;
 23 import org.springframework.beans.BeansException;
 24 import org.springframework.beans.factory.InitializingBean;
 25 import org.springframework.context.ApplicationContext;
 26 import org.springframework.context.ApplicationContextAware;
 27 import org.springframework.context.ConfigurableApplicationContext;
 28 import org.springframework.core.io.Resource;
 29 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 30 import org.springframework.core.io.support.ResourcePatternResolver;
 31 
 32 /**
 33  * 用于重新加载Mapper的工具
 34  */
 35 public class MybatisMapperLoadUtil implements InitializingBean, ApplicationContextAware {
 36     // 日志记录器
 37         private final Logger logger = Logger.getLogger(this.getClass());
 38     private final HashMap<String, String> mappers = new HashMap<String, String>();
 39     private volatile ConfigurableApplicationContext context = null;
 40     private volatile Scanner scanner = null;
 41 
 42     @Override
 43     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
 44         this.context = (ConfigurableApplicationContext) applicationContext;
 45     }
 46 
 47     @Override
 48     public void afterPropertiesSet() throws Exception {
 49         setScanner(new Scanner());
 50         /*try {
 51             
 52             new Timer(true).schedule(new TimerTask() {
 53                 public void run() {
 54                     try {
 55                         if("off".equals(ConfigService.getConfigRealTime(ConfigService.DYNAMIC_LOAD_MYBATIS_XML_SWITCH))) {
 56                             
 57                         }else {
 58                             if (scanner.isChanged()) {
 59                                 System.out.println("load mapper.xml");
 60                                 scanner.reloadXML();
 61                             }
 62                         }
 63 
 64                     } catch (Exception e) {
 65                         e.printStackTrace();
 66                     }
 67                 }
 68             }, 10 * 1000, 5 * 1000);
 69         } catch (Exception e1) {
 70             e1.printStackTrace();
 71         }*/
 72     }
 73 
 74     public Scanner getScanner() {
 75         return scanner;
 76     }
 77 
 78     public void setScanner(Scanner scanner) {
 79         this.scanner = scanner;
 80     }
 81 
 82     @SuppressWarnings("unchecked")
 83     public
 84     class Scanner {
 85         //此处应调整为可配置
 86         private static final String XML_RESOURCE_PATTERN = "**/model/*mybatis.xml";//ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + "**/*Mapper.xml";
 87         private final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
 88         public Scanner() throws IOException {
 89             Resource[] resources = findResource();
 90             if (resources != null) {
 91                 for (Resource resource : resources) {
 92                     String key = resource.getURI().toString();
 93                     String value = getMd(resource);
 94                     mappers.put(key, value);
 95                 }
 96             }
 97         }
 98         public void reloadXML() throws Exception {
 99             SqlSessionFactory factory = context.getBean(SqlSessionFactory.class);
100             Configuration configuration = factory.getConfiguration();
101             
102             removeConfig(configuration);
103             
104 
105             //获取新的mybatis-config文件配置 2016年1月5日17:49:37
106             InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
107             
108             try {
109                 XPathParser parser = new XPathParser(inputStream, true, null, new XMLMapperEntityResolver());
110                 for (XNode child : parser.evalNode("/configuration").evalNode("mappers").getChildren()) {
111                     String resourcePath = child.getStringAttribute("resource");
112                     Resource resource = resourcePatternResolver.getResource(resourcePath);
113                     XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(), configuration, resource.toString(), configuration.getSqlFragments());
114                     xmlMapperBuilder.parse();
115 
116                 }
117               } catch (Exception e) {
118                 throw ExceptionFactory.wrapException("Error building SqlSession.", e);
119               } finally {
120                 ErrorContext.instance().reset();
121                 try {
122                   inputStream.close();
123                 } catch (IOException e) {
124                   // Intentionally ignore. Prefer previous error.
125                 }
126               }
127         }
128         private void removeConfig(Configuration configuration) throws Exception {
129             Class<?> classConfig = configuration.getClass();
130             clearMap(classConfig, configuration, "mappedStatements");
131             clearMap(classConfig, configuration, "caches");
132             clearMap(classConfig, configuration, "resultMaps");
133             clearMap(classConfig, configuration, "parameterMaps");
134             clearMap(classConfig, configuration, "keyGenerators");
135             clearMap(classConfig, configuration, "sqlFragments");
136             clearSet(classConfig, configuration, "loadedResources");
137         }
138         private void clearMap(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
139             Field field = classConfig.getDeclaredField(fieldName);
140             field.setAccessible(true);
141             ((Map) field.get(configuration)).clear();
142         }
143         private void clearSet(Class<?> classConfig, Configuration configuration, String fieldName) throws Exception {
144             Field field = classConfig.getDeclaredField(fieldName);
145             field.setAccessible(true);
146             ((Set) field.get(configuration)).clear();
147         }
148         public boolean isChanged() throws IOException {
149             boolean isChanged = false;
150             for (Resource resource : findResource()) {
151                 String key = resource.getURI().toString();
152                 String value = getMd(resource);
153                 if (!value.equals(mappers.get(key))) {
154                     isChanged = true;
155                     mappers.put(key, value);
156                 }
157             }
158             return isChanged;
159         }
160         private Resource[] findResource() throws IOException {
161             return resourcePatternResolver.getResources(XML_RESOURCE_PATTERN);
162         }
163         private String getMd(Resource resource) throws IOException {
164             return new StringBuilder().append(resource.contentLength()).append("-").append(resource.lastModified()).toString();
165         }
166     }
167 }
原文地址:https://www.cnblogs.com/flying607/p/5103300.html