SpringMVC+Mybatis+热部署mapper文件

来源:互联网 发布:优化蜜蜡能买吗 编辑:程序博客网 时间:2024/05/15 03:31

SpringMVC+Mybatis+热部署mapper文件

每天都是从网上找别人分享出来的好东西纳入囊中,今天自己也想分享一下自己的一些东西给大家。

一直在用SSH框架,没办法现在的主流就是SpringMvc+Mybatis,所以也研究了一下。看了几天网上分享的精髓,恕小弟我愚昧,搞了好久才弄明白其中的奥妙,不过我觉得自己懂了还不够深刻,必须拿出来和大家分享,让大家也能看懂才是真正的懂了。

我尽量写的简单点通俗易懂,只要是有点java基础就能看懂这篇文章是我的目标。

我们老大最近让了解markDown,写标题的时候正好看到有‘切换markDown编辑器’,直接开干,之前真的一点也不了解markDown。

(奥利给,我次有内,为给呀,老铁没毛病,今天又是一个楼面,100来平方,轻松拿下,干就完了!!)不要问我这句话啥意思,最近快手上有个雷哥,因这句口头禅火了。废话是不是有点太多了?好吧,我错了步入正题!!!

我发现一个问题,也可能是我自己的问题,就是在看别人分享出来的资源的时候,总是跟着资源一步一步做,然后突然卡壳,要不就是报错要不就是各种纠结,瞬间继续看下去的心情就没了,这里建议大家耐心点,哪里卡壳了,就好好研究一下,当你迈过这个坎后,你肯定会收获更多

开发工具

Myeclipse2014jdk1.7tomcat7,数据库我用的是oracle,伙计们这几个东西都先给我准备好了,马上开始打仗了。什么?这些东西你都不知道?用我们老家的口头禅来说“外日他dei儿,你给我去求吧”,这是作为一个程序员必须知道的,就像你打仗需要用枪一个道理!

愤怒感言

每次跟着网上的资料学习,都会被一大堆的各种jar问题包搞的晕头转向,我总觉得这个是最浪费时间的,而且是能让人发疯的节奏!所以,这里我就先来拯救一下正在看我文章的小伙伴们吧,谁让你我最亲呢!我这里把所有jar包先贴出来,然后附上下载地址,请小伙伴们先不要问jar包的具体用途,先下载用了再说。
jar所有需要的jar包

下载链接:http://download.csdn.net/detail/chunge48596/9709211
好了,小伙伴,我们离成功就差一步了,要不咱们先喝杯茶聊聊妹子聊聊人生吧。Set Fire to the Rain好听,你值得拥有

项目结构

接下来我先把项目结构贴出来,有心的小伙伴可能会发现怎么看着有点眼熟?没办法,我也是从网上找的资源拼凑的,大家凑合着看吧。还想咋滴?不行咱们来打一架?哼~
项目结构

卧槽,刚才手机振动了一下,打开一看居然发工资了,我这小心脏扑通扑通的,老板:给我来个鸡蛋灌饼,加2个蛋!!!!老子有钱

开始盖楼

在Package Explorer空白处右键 > new > Web Project

这里写图片描述

next>next>各种next,最后Finish,然后出现如下结构

这里写图片描述

然后咱们把上面讲到的jar包全部放进项目里,第一步打开项目家大门,第二部把jar包拿起来,第三部使劲把这些jar包扔进项目家里!!!

不逗你们啦,我是这样弄的,去Workspaces找到你刚建立好的项目,然后把所有jar包放进lib目录下,我的项目路径 > D:\Workspaces2014\spring-mvc\WebRoot\WEB-INF\lib

不知道自己的Workspaces项目路径在哪?我勒个擦,我的小哥,你确定你是个程序员吗?我再教教你,谁让我就是这么好呢!!!以后给我记住了,八嘎
右键你的项目名称 > Properties > Resource 然后你看到了什么?哦~ ~ ~ ~ ~知道了,在这里啊!

这里写图片描述

下面就是数据库连接了,建立JDBC属性文件,项目都是这样,把数据库配置独立出来,这样是极好的

右键src > new > File,名字取名叫 jdbc.properties > Finish
右键 jdbc.properties > Properties

这里写图片描述

将 jdbc.properties 文件编码修改为UTF-8

jdbc.properties 里面复制下面数据库配置,这里请注意,我用的是oracle 用其他数据库的小伙伴要注意哦!当然这里需要配置你自己的数据库配置,这里如果你不会,那么我建议去问一下旁边的老师,或者同事,请人家吃麻辣烫。你想问我啊?也行,我要喝16块钱一碗的方中山胡辣汤,嘎嘎!

jdbc.driver=oracle.jdbc.OracleDriver#test environmentjdbc.url=jdbc\:oracle\:thin\:@192.111.111.111\:1521\:oraga1jdbc.username=bugaosunijdbc.password=nicai#jdbc.maxActive=1000#jdbc.maxIdle=300#jdbc.maxWait=60000#defaultAutoCommit=false#removeAbandoned=true#removeAbandonedTimeout=600#jdbc.validationQuery=select 1 from dual#jdbc.testOnBorrow=true

只是一个简单的一个SpringMvc例子,所以上面很多数据库连接池的配置我都先注释掉了,想要强大的伙伴自己去研究研究吧!

创建log4j.properties文件,里面的注释异常的详细,不多说了,直接贴出代码

记得把把文件格式转换成utf-8

### Log4j配置 ###### 与Spring结合需要在web.xml中指定此文件位置,并添加监听器 ####定义log4j的输出级别和输出目的地(目的地可以自定义名称,和后面的对应)#[ level ] , appenderName1 , appenderName2log4j.rootLogger=DEBUG,console,file#-----------------------------------##1 定义日志输出目的地为控制台log4j.appender.console = org.apache.log4j.ConsoleAppenderlog4j.appender.console.Target = System.outlog4j.appender.console.Threshold=DEBUG####可以灵活地指定日志输出格式,下面一行是指定具体的格式 ####%c: 输出日志信息所属的类目,通常就是所在类的全名#%m: 输出代码中指定的消息,产生的日志具体信息 #%n: 输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"输出日志信息换行log4j.appender.console.layout = org.apache.log4j.PatternLayoutlog4j.appender.console.layout.ConversionPattern=[%c]-%m%n#-----------------------------------##2 文件大小到达指定尺寸的时候产生一个新的文件 log4j.appender.file = org.apache.log4j.RollingFileAppender#日志文件输出目录log4j.appender.file.File=logs/ssm.log#定义文件最大大小log4j.appender.file.MaxFileSize=10mb###输出日志信息####最低级别log4j.appender.file.Threshold=ERRORlog4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n#-----------------------------------##4 mybatis 输出SQL语句部分log4j.logger.org.mybatis=DEBUG#log4j.logger.cn.tibet.cas.dao=DEBUG#log4j.logger.org.mybatis.common.jdbc.SimpleDataSource=DEBUG##log4j.logger.org.mybatis.common.jdbc.ScriptRunner=DEBUG##log4j.logger.org.mybatis.sqlmap.engine.impl.SqlMapClientDelegate=DEBUG##log4j.logger.java.sql.Connection=DEBUGlog4j.logger.java.sql=DEBUGlog4j.logger.java.sql.Statement=DEBUGlog4j.logger.java.sql.ResultSet=DEBUGlog4j.logger.java.sql.PreparedStatement=DEBUG 

建立spring-mybatis.xml配置文件,很重要的一步哦,同学们要给我竖起耳朵听着,瞪大眼睛看着

右键src > new > File,名字取名叫 spring-mybatis.xml > Finish,记得看一下文件编码格式,不是UTF-8的修改一下
spring-mybatis.xml配置文件,主要的就是自动扫描,自动注入,配置数据库。

<?xml version="1.0" encoding="UTF-8"?>    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"         xmlns:context="http://www.springframework.org/schema/context"         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">      <!-- 自动扫描,base-package指向了alibaba下面的所有包,扫描所有类的注解 -->      <context:component-scan base-package="com.alibaba" />     <!-- 引入配置文件,这里注意properties文件最好还是放在src下面吧,本来放在WEB-INF下面搞了好久都报错 -->      <context:property-placeholder location="classpath:jdbc.properties" />    <!--数据库连接-->      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">           <property name="driverClassName" value="${jdbc.driver}" />        <property name="url" value="${jdbc.url}" />          <property name="username" value="${jdbc.username}"/>          <property name="password" value="${jdbc.password}"/>          <!--          配置初始化大小、最小、最大         <property name="initialSize"><value>1</value></property>          <property name="maxActive"><value>5</value></property>          <property name="minIdle"><value>1</value></property>          配置获取连接等待超时的时间          <property name="maxWait"><value>60000</value></property>          配置监控统计拦截的filters          <property name="filters"><value>stat</value></property>          配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒          <property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>          配置一个连接在池中最小生存的时间,单位是毫秒          <property name="minEvictableIdleTimeMillis"><value>300000</value></property>         -->      </bean>      <!-- spring和MyBatis整合,不需要mybatis的配置映射文件 -->      <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">          <property name="dataSource" ref="dataSource" />          <!-- 自动扫描mapping.xml文件 -->          <property name="mapperLocations" value="classpath:com/alibaba/mapper/*.xml"></property>      </bean>      <!-- DAO接口所在包名,Spring会自动查找其下的类 -->      <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">          <property name="basePackage" value="com.alibaba.dao" />          <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>      </bean>      <!-- (事务管理)transaction manager, use JtaTransactionManager for global tx -->      <bean id="transactionManager"          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">          <property name="dataSource" ref="dataSource" />      </bean></beans> 

上面的步骤完成后,我们用MyBatis Generator自动创建代码(dao,entity,mapper),这步很牛逼,当你实战的时候能为你省下不少时间,跟网上的大神学的

在D盘,或者随便哪个盘里面创建一个文件夹,名字自取。文件夹里面的内容如下:这里写图片描述

属实操蛋了,写完预览了一下,发现博客都看不清楚包的名字,我在列一下包名和文件名:
generatorConfig.xml
mybatis-3.2.7.jar
mybatis-generator-core-1.3.2.jar
mysql-connector-java-5.1.25-bin.jar
ojdbc14.jar

generatorConfig.xml内容如下

<?xml version="1.0" encoding="UTF-8"?>    <!DOCTYPE generatorConfiguration      PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"      "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">    <generatorConfiguration>    <!-- 注意注释的前后都是有空格的,不然会报错 -->    <!-- oracle数据库驱动 -->    <classPathEntry location="ojdbc14.jar"/>    <!-- mysql数据库驱动,我用的是oracle驱动 -->    <!-- <classPathEntry location="mysql-connector-java-5.1.25-bin.jar"/> -->    <context id="DB2Tables"  targetRuntime="MyBatis3">        <commentGenerator>            <property name="suppressDate" value="true"/>            <!-- 是否去除自动生成的注释true:是:false:否 -->            <property name="suppressAllComments" value="true"/>        </commentGenerator>        <!-- oralce数据库链接URL,用户名、密码 -->        <jdbcConnection driverClass="oracle.jdbc.driver.OracleDriver" connectionURL="jdbc:oracle:thin:@192.168.38.207:1521:oradev" userId="xxd_v6_test" password="xxd_v6_test">        <!-- mysql数据库链接URL,用户名、密码 -->        <!-- <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://122.122.2.1/db_124" userId="test" password="test"> -->        </jdbcConnection>        <javaTypeResolver>            <property name="forceBigDecimals" value="false"/>        </javaTypeResolver>        <!-- 生成模型的包名和位置 -->        <javaModelGenerator targetPackage="test.domain" targetProject="src">            <property name="enableSubPackages" value="true"/>            <property name="trimStrings" value="true"/>        </javaModelGenerator>        <!-- 生成映射文件的包名和位置 -->        <sqlMapGenerator targetPackage="test.mapping" targetProject="src">            <property name="enableSubPackages" value="true"/>        </sqlMapGenerator>        <!-- 生成DAO的包名和位置 -->        <javaClientGenerator type="XMLMAPPER" targetPackage="test.IDao" targetProject="src">            <property name="enableSubPackages" value="true"/>        </javaClientGenerator>        <!-- 要生成的表 tableName是数据库中的表名或视图名 domainObjectName是实体类名 -->        <table tableName="industry" domainObjectName="industry" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>    </context></generatorConfiguration>

以上这些都弄好之后,用控制台进入当前目录下,按照我的步骤来:

1、按Ctrl + r 输入 cmd 回车,进入控制台
2、输入 d: 回车(这里取决于你的文件夹在哪个盘里)
3、输入 cd 文件夹名字 回车(注意cd后面有个空格)
4、输入 Java -jar mybatis-generator-core-1.3.2.jar -configfile generatorConfig.xml -overwrite 回车

然后稍等一下,出现以下提示及表示成功
这里写图片描述

然后你就可以去看看src文件夹里面的东西了,这里需要注意下生成的mapper文件,里面好像有点重复了,耐心点看看是否重复了,有重复就把重复的部分去掉即可

接下来我们进行测试我们的代码是否能成功运行

将生成的文件复制到我们的项目里面,如下图:

这里写图片描述

不是说贴进来就行了,肯定会报错,把错误改改,就是一些包的位置和引入错误,改好之后需要注意一下mapper.xml文件,我接下来给伙伴们说一下mapper.xml文件各种关键字对应的位置和意思

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- 这里的namespace对应的是dao --><mapper namespace="com.alibaba.dao.industryMapper">  <!-- type对应的是实体类;我用的是oracle数据库,数字类型字段要用NUMERIC这个类型,用NUMBER这个类型会报错 -->   <resultMap id="BaseResultMap" type="com.alibaba.entity.industry">    <id column="ID" jdbcType="DECIMAL" property="id" />    <result column="CATEGORY_LEVEL" jdbcType="DECIMAL" property="categoryLevel" />    <result column="PARENT_ID" jdbcType="DECIMAL" property="parentId" />    <result column="CATEGORY_NAME" jdbcType="VARCHAR" property="categoryName" />    <result column="CATEGORY_EXPLAIN" jdbcType="VARCHAR" property="categoryExplain" />    <result column="PROFIT_MARGIN" jdbcType="DECIMAL" property="profitMargin" />    <result column="CREATE_DATE" jdbcType="DATE" property="createDate" />    <result column="UPDATE_DATE" jdbcType="DATE" property="updateDate" />    <result column="REMARK" jdbcType="VARCHAR" property="remark" />  </resultMap>  <!-- Base_Column_List就相当于你需要查询的字段,完全可以用select * 来替代啊,不太明白这里为什么会自动生成此项 -->  <sql id="Base_Column_List">    ID, CATEGORY_LEVEL, PARENT_ID, CATEGORY_NAME, CATEGORY_EXPLAIN, PROFIT_MARGIN, CREATE_DATE,     UPDATE_DATE, REMARK  </sql>  <!-- id就是dao里面定义的方法,要保持一致,这里注意,我把parameterType中的Long改成了Integer -->  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">    select     <include refid="Base_Column_List" />    from INDUSTRY    where ID = #{id,jdbcType=DECIMAL}  </select></mapper>

太费劲了,我只贴出来一部分代码,后面那些更新和删除就不贴出来了,就简单的给大家演示一下查询,我相信在我的调教下,这个查询会了之后,其他的比葫芦画瓢,你绝对能学会~

接下来我们就可以进行测试了,创建test、service、serviceImpl三个文件,下面贴出来代码

这里写图片描述

industryService:

package com.alibaba.service;import com.alibaba.entity.industry;public interface industryService {    //根据ID查询行业信息    public industry selectByPrimaryKey(Integer id);}

industryServiceImpl:

package com.alibaba.service.serviceImpl;import javax.annotation.Resource;import org.springframework.stereotype.Service;import com.alibaba.dao.industryMapper;import com.alibaba.entity.industry;import com.alibaba.service.industryService;@Servicepublic class industryServiceImpl implements industryService{    @Resource    private industryMapper industryDao;    //根据id查询行业信息    public industry selectByPrimaryKey(Integer id){        return industryDao.selectByPrimaryKey(id);    }}

test:

package com.alibaba.controller;import javax.annotation.Resource;import org.apache.log4j.Logger;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import com.alibaba.entity.industry;import com.alibaba.service.industryService;@RunWith(SpringJUnit4ClassRunner.class)     //表示继承了SpringJUnit4ClassRunner类 @ContextConfiguration(locations = {"classpath:spring-mybatis.xml"}) public class test {    private static Logger logger = Logger.getLogger(test.class);     @Resource    private industryService iService;    @Test    public void test2(){        industry i = iService.selectByPrimaryKey(3);        System.out.println("行业说明:"+i.getCategoryExplain());        logger.info("行业说明:"+i.getCategoryExplain());    }}

一切准备就绪,打开test文件,右键 > Run As > JUnit Test,看控制台有没有输出你的数据,有数据,说明说明你已炼成葵花宝典第一式

这里写图片描述

下面创建spring-mvc.xml文件,SpringMvc的核心

直接贴出配置

<?xml version="1.0" encoding="UTF-8"?>  <beans xmlns="http://www.springframework.org/schema/beans"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"      xmlns:context="http://www.springframework.org/schema/context"      xmlns:mvc="http://www.springframework.org/schema/mvc"      xsi:schemaLocation="http://www.springframework.org/schema/beans                            http://www.springframework.org/schema/beans/spring-beans-3.1.xsd                            http://www.springframework.org/schema/context                            http://www.springframework.org/schema/context/spring-context-3.1.xsd                            http://www.springframework.org/schema/mvc                            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">     <!-- 自动扫描该包,使SpringMVC认为包下用了@controller注解的类是控制器 -->      <context:component-scan base-package="com.alibaba.controller" />      <!--避免IE执行AJAX时,返回JSON出现下载文件 -->      <bean id="mappingJacksonHttpMessageConverter"          class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">          <property name="supportedMediaTypes">              <list>                  <value>text/html;charset=UTF-8</value>              </list>          </property>      </bean>      <!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->      <bean          class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">          <property name="messageConverters">              <list>                  <ref bean="mappingJacksonHttpMessageConverter" /> <!-- JSON转换器 -->              </list>          </property>      </bean>      <!-- 定义跳转的文件的前后缀 ,视图模式配置-->      <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">          <!-- 这里的配置我的理解是controller方法返回一个字符串,然后在WEB-INFO/pages/里面找与方法名对应的jsp-->          <property name="prefix" value="/WEB-INF/pages/" />          <property name="suffix" value=".jsp" />      </bean>      <!-- 配置文件上传,如果没有使用文件上传可以不用配置,当然如果不配,那么配置文件中也不必引入上传组件包 -->      <bean id="multipartResolver"            class="org.springframework.web.multipart.commons.CommonsMultipartResolver">            <!-- 默认编码 -->          <property name="defaultEncoding" value="utf-8" />            <!-- 文件大小最大值 -->          <property name="maxUploadSize" value="10485760000" />            <!-- 内存中的最大值 -->          <property name="maxInMemorySize" value="40960" />        </bean>   </beans>  

在WEB-INF下创建web.xml,配置如下:

<?xml version="1.0" encoding="UTF-8"?>  <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns="http://java.sun.com/xml/ns/javaee"      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"      version="3.0">      <display-name>Archetype Created Web Application</display-name>      <!-- Spring和mybatis的配置文件 -->      <context-param>          <param-name>contextConfigLocation</param-name>          <param-value>classpath:spring-mybatis.xml</param-value>      </context-param>      <!-- 编码过滤器 -->      <filter>          <filter-name>encodingFilter</filter-name>          <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>          <async-supported>true</async-supported>          <init-param>              <param-name>encoding</param-name>              <param-value>UTF-8</param-value>          </init-param>      </filter>      <filter-mapping>          <filter-name>encodingFilter</filter-name>          <url-pattern>/*</url-pattern>      </filter-mapping>      <!-- Spring监听器 -->      <listener>          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>      </listener>      <!-- 防止Spring内存溢出监听器 -->      <listener>          <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>      </listener>     <!-- Spring MVC servlet -->      <servlet>          <servlet-name>SpringMVC</servlet-name>          <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>          <init-param>              <param-name>contextConfigLocation</param-name>              <param-value>classpath:spring-mvc.xml</param-value>          </init-param>          <load-on-startup>1</load-on-startup>          <async-supported>true</async-supported>      </servlet>      <servlet-mapping>          <servlet-name>SpringMVC</servlet-name>          <!-- 此处如果用“/”表示拦截所有请求,包括静态资源(js,css,jpg,)需要过滤掉这些静态资源的拦截;                此处配置成*.do,那么就只会拦截后缀为.do的请求,不会拦截静态资源,也不用配置过滤静态资源,推荐使用 -->          <url-pattern>*.do</url-pattern>      </servlet-mapping>     <welcome-file-list>          <welcome-file>/index.jsp</welcome-file>      </welcome-file-list> </web-app>  

在controller包里创建industryController(名字自定义):

package com.alibaba.controller;import javax.annotation.Resource;import javax.servlet.http.HttpServletRequest;import org.apache.log4j.Logger;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import com.alibaba.entity.industry;import com.alibaba.service.industryService;@Controller@RequestMapping("/industry")public class industryController {    private static Logger logger = Logger.getLogger(industryController.class);     private industry indu;    @Resource     private industryService iservice;    @RequestMapping("/queryIndustry")    public String queryIndustryById(HttpServletRequest request,String id){        /*接收前台传过来的参数,可以直接接收,不需要任何多余的代码,就直接在方法的参数里面定义好就行,牛逼思密达*/        /*这里需要注意,如果参数只有一个,url传过来的参数名称和controller方法里面的参数名称不对应也能接收到值;如果是多个参数,那就必须一一对应,不然会接收不到值*/        indu = iservice.selectByPrimaryKey(Integer.parseInt(id));        request.getSession().setAttribute("industry", indu);        return "showIndustry";    }}

index.jsp,如下:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">    <title>My JSP 'index.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="styles.css">    -->  </head>  <body>    <a href="industry/queryIndustry.do?id=3">点击查询行业信息</a>  </body></html>

在WEB-INF下创建pages文件夹,然后创建showIndustry.jsp,名字不是随便起的,跟你controller方法返回的字符串要对应

这里写图片描述

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">    <title>My JSP 'index.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache">    <meta http-equiv="cache-control" content="no-cache">    <meta http-equiv="expires" content="0">        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">    <meta http-equiv="description" content="This is my page">    <!--    <link rel="stylesheet" type="text/css" href="styles.css">    -->  </head>  <body>    <table align="center" border="1">        <tr>            <td>行业名称</td>            <td>${industry.categoryName }</td>        </tr>        <tr>            <td>行业说明</td>            <td>${industry.categoryExplain }</td>        </tr>    </table>  </body></html>

差不多要结束了,我们把项目部署到tomcat7下,然后运行项目

这里写图片描述

打开浏览器,输入:http://localhost:8080/spring-mvc

这里写图片描述

“点击查询行业信息”

这里写图片描述

大功告成,艾玛,真累,到这里SpringMvc伙伴们就差不多学会了,我建议大家还是多看几遍过程,哪个地方不会去搜一下,或者你只需要一碗胡辣汤贿赂贿赂我,我就勉为其难的给你讲讲撒,哈哈,开个玩笑啦

已经学会的同学可能会发现一个问题,就是每次我们修改一下mapper文件,就需要重启一下项目。

项目小了还好,如果以后项目大了,修改一下mapper,重启一下项目,这尼玛蛋都碎一地了

所以,又费老鼻子劲去找方法,最终功夫不负有心人,接下来,就给大家讲讲自动加载mapper文件的方法

这个东西挺有意思,只要发现任何mapper文件被修改,就会重新加载被修改的mapper文件,只加载被修改的mapper文件,只加载被修改的mapper文件,只加载被修改的mapper文件重要的事情说三遍!!!网上还有些方法也能实现自动加载mapper文件,不过我觉得麻烦,而且每次修改一个mapper文件,就需要重新加载所有的mapper文件,效率上也不会太好,废话不多说,直接开始

在src下创建util包,然后创建一个类,名字:MapperRefresh

这里写图片描述

然后把下面这一大坨代码贴进MapperRefresh.java,里面的代码说实话我也没怎么看,说不定也看不懂,先拿起来用吧

package com.alibaba.util;import java.io.File;  import java.io.FileInputStream;  import java.io.FileNotFoundException;  import java.io.InputStream;  import java.lang.reflect.Field;  import java.util.ArrayList;  import java.util.HashMap;  import java.util.List;  import java.util.Map;  import java.util.Properties;  import java.util.Set;  import org.apache.commons.lang3.StringUtils;  import org.apache.ibatis.builder.xml.XMLMapperBuilder;  import org.apache.ibatis.executor.ErrorContext;  import org.apache.ibatis.session.Configuration;  import org.apache.log4j.Logger;  import org.springframework.core.NestedIOException;  import org.springframework.core.io.Resource;  import com.google.common.collect.Sets;  /**  * 刷新MyBatis Mapper XML 线程  * @author ThinkGem 这个是原著的作者,我只是直接拿来用了,原著莫怪 * @version 2016-5-29  */  public class MapperRefresh implements java.lang.Runnable {      public static Logger log = Logger.getLogger(MapperRefresh.class);      private static String filename = "/mybatis-refresh.properties";      private static Properties prop = new Properties();      private static boolean enabled;         // 是否启用Mapper刷新线程功能      private static boolean refresh;         // 刷新启用后,是否启动了刷新线程      private Set<String> location;         // Mapper实际资源路径      private Resource[] mapperLocations;     // Mapper资源路径      private Configuration configuration;        // MyBatis配置对象      private Long beforeTime = 0L;           // 上一次刷新时间      private static int delaySeconds;        // 延迟刷新秒数      private static int sleepSeconds;        // 休眠时间      private static String mappingPath;      // xml文件夹匹配字符串,需要根据需要修改      static {          try {              prop.load(MapperRefresh.class.getResourceAsStream(filename));          } catch (Exception e) {              e.printStackTrace();              System.out.println("Load mybatis-refresh “"+filename+"” file error.");          }          enabled = "true".equalsIgnoreCase(getPropString("enabled"));          delaySeconds = getPropInt("delaySeconds");          sleepSeconds = getPropInt("sleepSeconds");          mappingPath = getPropString("mappingPath");          delaySeconds = delaySeconds == 0 ? 50 : delaySeconds;          sleepSeconds = sleepSeconds == 0 ? 3 : sleepSeconds;          mappingPath = StringUtils.isBlank(mappingPath) ? "mappings" : mappingPath;          log.debug("[enabled] " + enabled);          log.debug("[delaySeconds] " + delaySeconds);          log.debug("[sleepSeconds] " + sleepSeconds);          log.debug("[mappingPath] " + mappingPath);      }      public static boolean isRefresh() {          return refresh;      }      public MapperRefresh(Resource[] mapperLocations, Configuration configuration) {          this.mapperLocations = mapperLocations;          this.configuration = configuration;      }      @Override      public void run() {          beforeTime = System.currentTimeMillis();          log.debug("[location] " + location);          log.debug("[configuration] " + configuration);          if (enabled) {              // 启动刷新线程              final MapperRefresh runnable = this;              new Thread(new java.lang.Runnable() {                  @Override                  public void run() {                      if (location == null){                          location = Sets.newHashSet();                          log.debug("MapperLocation's length:" + mapperLocations.length);                          for (Resource mapperLocation : mapperLocations) {                              String s = mapperLocation.toString().replaceAll("\\\\", "/");                              s = s.substring("file [".length(), s.lastIndexOf(mappingPath) + mappingPath.length());                              if (!location.contains(s)) {                                  location.add(s);                                  log.debug("Location:" + s);                              }                          }                          log.debug("Locarion's size:" + location.size());                      }                      try {                          Thread.sleep(delaySeconds * 1000);                      } catch (InterruptedException e2) {                          e2.printStackTrace();                      }                      refresh = true;                      System.out.println("========= Enabled refresh mybatis mapper =========");                      while (true) {                          try {                              for (String s : location) {                                  runnable.refresh(s, beforeTime);                              }                          } catch (Exception e1) {                              e1.printStackTrace();                          }                          try {                              Thread.sleep(sleepSeconds * 1000);                          } catch (InterruptedException e) {                              e.printStackTrace();                          }                      }                  }              }, "MyBatis-Mapper-Refresh").start();          }      }      /**      * 执行刷新      * @param filePath 刷新目录      * @param beforeTime 上次刷新时间      * @throws NestedIOException 解析异常      * @throws FileNotFoundException 文件未找到      * @author ThinkGem      */      @SuppressWarnings({ "rawtypes", "unchecked" })      private void refresh(String filePath, Long beforeTime) throws Exception {          // 本次刷新时间          Long refrehTime = System.currentTimeMillis();          // 获取需要刷新的Mapper文件列表          List<File> fileList = this.getRefreshFile(new File(filePath), beforeTime);          if (fileList.size() > 0) {              log.debug("Refresh file: " + fileList.size());          }          for (int i = 0; i < fileList.size(); i++) {              InputStream inputStream = new FileInputStream(fileList.get(i));              String resource = fileList.get(i).getAbsolutePath();              try {                  // 清理原有资源,更新为自己的StrictMap方便,增量重新加载                  String[] mapFieldNames = new String[]{                      "mappedStatements", "caches",                      "resultMaps", "parameterMaps",                      "keyGenerators", "sqlFragments"                  };                  for (String fieldName : mapFieldNames){                      Field field = configuration.getClass().getDeclaredField(fieldName);                      field.setAccessible(true);                      Map map = ((Map)field.get(configuration));                      if (!(map instanceof StrictMap)){                          Map newMap = new StrictMap(StringUtils.capitalize(fieldName) + "collection");                          for (Object key : map.keySet()){                              try {                                  newMap.put(key, map.get(key));                              }catch(IllegalArgumentException ex){                                  newMap.put(key, ex.getMessage());                              }                          }                          field.set(configuration, newMap);                      }                  }                  // 清理已加载的资源标识,方便让它重新加载。                  Field loadedResourcesField = configuration.getClass().getDeclaredField("loadedResources");                  loadedResourcesField.setAccessible(true);                  Set loadedResourcesSet = ((Set)loadedResourcesField.get(configuration));                  loadedResourcesSet.remove(resource);                  //重新编译加载资源文件。                  XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(inputStream, configuration,                           resource, configuration.getSqlFragments());                  xmlMapperBuilder.parse();              } catch (Exception e) {                  throw new NestedIOException("Failed to parse mapping resource: '" + resource + "'", e);              } finally {                  ErrorContext.instance().reset();              }              System.out.println("Refresh file: " + mappingPath + StringUtils.substringAfterLast(fileList.get(i).getAbsolutePath(), mappingPath));              if (log.isDebugEnabled()) {                  log.debug("Refresh file: " + fileList.get(i).getAbsolutePath());                  log.debug("Refresh filename: " + fileList.get(i).getName());              }          }          // 如果刷新了文件,则修改刷新时间,否则不修改          if (fileList.size() > 0) {              this.beforeTime = refrehTime;          }      }      /**      * 获取需要刷新的文件列表      * @param dir 目录      * @param beforeTime 上次刷新时间      * @return 刷新文件列表      */      private List<File> getRefreshFile(File dir, Long beforeTime) {          List<File> fileList = new ArrayList<File>();          File[] files = dir.listFiles();          if (files != null) {              for (int i = 0; i < files.length; i++) {                  File file = files[i];                  if (file.isDirectory()) {                      fileList.addAll(this.getRefreshFile(file, beforeTime));                  } else if (file.isFile()) {                      if (this.checkFile(file, beforeTime)) {                          fileList.add(file);                      }                  } else {                      System.out.println("Error file." + file.getName());                  }              }          }          return fileList;      }      /**      * 判断文件是否需要刷新      * @param file 文件      * @param beforeTime 上次刷新时间      * @return 需要刷新返回true,否则返回false      */      private boolean checkFile(File file, Long beforeTime) {          if (file.lastModified() > beforeTime) {              return true;          }          return false;      }      /**      * 获取整数属性      * @param key      * @return      */      private static int getPropInt(String key) {          int i = 0;          try {              i = Integer.parseInt(getPropString(key));          } catch (Exception e) {          }          return i;      }      /**      * 获取字符串属性      * @param key      * @return      */      private static String getPropString(String key) {          return prop == null ? null : prop.getProperty(key);      }      /**      * 重写 org.apache.ibatis.session.Configuration.StrictMap 类      * 来自 MyBatis3.4.0版本,修改 put 方法,允许反复 put更新。      */      public static class StrictMap<V> extends HashMap<String, V> {          private static final long serialVersionUID = -4950446264854982944L;          private String name;          public StrictMap(String name, int initialCapacity, float loadFactor) {              super(initialCapacity, loadFactor);              this.name = name;          }          public StrictMap(String name, int initialCapacity) {              super(initialCapacity);              this.name = name;          }          public StrictMap(String name) {              super();              this.name = name;          }          public StrictMap(String name, Map<String, ? extends V> m) {              super(m);              this.name = name;          }          @SuppressWarnings("unchecked")          public V put(String key, V value) {              // ThinkGem 如果现在状态为刷新,则刷新(先删除后添加)              if (MapperRefresh.isRefresh()) {                  remove(key);                  MapperRefresh.log.debug("refresh key:" + key.substring(key.lastIndexOf(".") + 1));              }              // ThinkGem end              if (containsKey(key)) {                  throw new IllegalArgumentException(name + " already contains value for " + key);              }              if (key.contains(".")) {                  final String shortKey = getShortName(key);                  if (super.get(shortKey) == null) {                      super.put(shortKey, value);                  } else {                      super.put(shortKey, (V) new Ambiguity(shortKey));                  }              }              return super.put(key, value);          }          public V get(Object key) {              V value = super.get(key);              if (value == null) {                  throw new IllegalArgumentException(name + " does not contain value for " + key);              }              if (value instanceof Ambiguity) {                  throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name                          + " (try using the full name including the namespace, or rename one of the entries)");              }              return value;          }          private String getShortName(String key) {              final String[] keyparts = key.split("\\.");              return keyparts[keyparts.length - 1];          }          protected static class Ambiguity {              private String subject;              public Ambiguity(String subject) {                  this.subject = subject;              }              public String getSubject() {                  return subject;              }          }      }  }  

MyBatis有几个不太好的地方,是当实体类别名重名的时候,Mapper XML有错误的时候,系统启动时会一直等待无法正常启动(其实是加载失败后又重新加载,进入了死循环),这里重写下SqlSessionFactoryBean.java文件,解决这个问题,在这个文件里也加入启动上面写的线程类:

1、修改实体类重名的时候抛出并打印异常,否则系统会一直递归造成无法启动。
2、MapperXML有错误的时候抛出并打印异常,否则系统会一直递归造成无法启动。
3、加入启动MapperRefresh.java线程服务。

我下面会把SqlSessionFactoryBean.java所涉及到需要修改的地方会标注出来。这里童鞋们可能会问去哪里找SqlSessionFactoryBean.java这个文件,我在这里卡壳了,这里也给大家说一下,这个类是在mybatis-spring-1.2.2.jar这个包里面,是一个class文件。

这不是坑人吗,怎么改这个SqlSessionFactoryBean.class文件?我的具体的思路就是,先把这个class文件反编译成java文件,然后再去修改这个java文件,然后再把这个java文件编译成class文件,然后再放进mybatis-spring-1.2.2.jar包里替换掉之前的SqlSessionFactoryBean.class

我自己看着都绕,我来一步一步教大家吧
1、去找一个反编译软件,很多反编译软件,我这里用的是jd-gui.exe
下载地址:http://download.csdn.net/detail/eyebrows_cs/5277552

2、把下载好的jd-gui.exe打开,然后把mybatis-spring-1.2.2.jar拖到里面,找到SqlSessionFactoryBean.class这个文件,呈现在你面前的就是一个反编译过来的java文件了

这里写图片描述

3、修改这个java文件,然后再编译成class文件,这步我一开始没想明白怎么弄,最后用了一个笨方法。在你的项目下新建一个包:右键src > new Package

这里写图片描述

点击Finish,然后再包下面建一个类,名字就叫:SqlSessionFactoryBean

4、把下面这一大坨代码,复制到SqlSessionFactoryBean.java里面,下面这一大坨代码,我在改动的地方都加上了“修改处”三个字!!!

package org.mybatis.spring;import java.io.IOException;import java.sql.SQLException;import java.util.Properties;import javax.sql.DataSource;import org.apache.ibatis.builder.xml.XMLConfigBuilder;import org.apache.ibatis.builder.xml.XMLMapperBuilder;import org.apache.ibatis.executor.ErrorContext;import org.apache.ibatis.logging.Log;import org.apache.ibatis.logging.LogFactory;import org.apache.ibatis.mapping.DatabaseIdProvider;import org.apache.ibatis.mapping.Environment;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.reflection.factory.ObjectFactory;import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.apache.ibatis.transaction.TransactionFactory;import org.apache.ibatis.type.TypeAliasRegistry;import org.apache.ibatis.type.TypeHandler;import org.apache.ibatis.type.TypeHandlerRegistry;import org.mybatis.spring.transaction.SpringManagedTransactionFactory;import org.springframework.beans.factory.FactoryBean;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationEvent;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.core.NestedIOException;import org.springframework.core.io.Resource;import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;import org.springframework.util.Assert;import org.springframework.util.ObjectUtils;import org.springframework.util.StringUtils;import com.alibaba.util.MapperRefresh;public class SqlSessionFactoryBean  implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent>{  private static final Log logger = LogFactory.getLog(SqlSessionFactoryBean.class);  private Resource configLocation;  private Resource[] mapperLocations;  private DataSource dataSource;  private TransactionFactory transactionFactory;  private Properties configurationProperties;  private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();  private SqlSessionFactory sqlSessionFactory;  private String environment = SqlSessionFactoryBean.class.getSimpleName();  private boolean failFast;  private Interceptor[] plugins;  private TypeHandler<?>[] typeHandlers;  private String typeHandlersPackage;  private Class<?>[] typeAliases;  private String typeAliasesPackage;  private Class<?> typeAliasesSuperType;  private DatabaseIdProvider databaseIdProvider;  private ObjectFactory objectFactory;  private ObjectWrapperFactory objectWrapperFactory;  public void setObjectFactory(ObjectFactory objectFactory)  {    this.objectFactory = objectFactory;  }  public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory)  {    this.objectWrapperFactory = objectWrapperFactory;  }  public DatabaseIdProvider getDatabaseIdProvider()  {    return this.databaseIdProvider;  }  public void setDatabaseIdProvider(DatabaseIdProvider databaseIdProvider)  {    this.databaseIdProvider = databaseIdProvider;  }  public void setPlugins(Interceptor[] plugins)  {    this.plugins = plugins;  }  public void setTypeAliasesPackage(String typeAliasesPackage)  {    this.typeAliasesPackage = typeAliasesPackage;  }  public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType)  {    this.typeAliasesSuperType = typeAliasesSuperType;  }  public void setTypeHandlersPackage(String typeHandlersPackage)  {    this.typeHandlersPackage = typeHandlersPackage;  }  public void setTypeHandlers(TypeHandler<?>[] typeHandlers)  {    this.typeHandlers = typeHandlers;  }  public void setTypeAliases(Class<?>[] typeAliases)  {    this.typeAliases = typeAliases;  }  public void setFailFast(boolean failFast)  {    this.failFast = failFast;  }  public void setConfigLocation(Resource configLocation)  {    this.configLocation = configLocation;  }  public void setMapperLocations(Resource[] mapperLocations)  {    this.mapperLocations = mapperLocations;  }  public void setConfigurationProperties(Properties sqlSessionFactoryProperties)  {    this.configurationProperties = sqlSessionFactoryProperties;  }  public void setDataSource(DataSource dataSource)  {    if ((dataSource instanceof TransactionAwareDataSourceProxy))    {      this.dataSource = ((TransactionAwareDataSourceProxy)dataSource).getTargetDataSource();    }    else this.dataSource = dataSource;  }  public void setSqlSessionFactoryBuilder(SqlSessionFactoryBuilder sqlSessionFactoryBuilder)  {    this.sqlSessionFactoryBuilder = sqlSessionFactoryBuilder;  }  public void setTransactionFactory(TransactionFactory transactionFactory)  {    this.transactionFactory = transactionFactory;  }  public void setEnvironment(String environment)  {    this.environment = environment;  }  public void afterPropertiesSet()    throws Exception  {    Assert.notNull(this.dataSource, "Property 'dataSource' is required");    Assert.notNull(this.sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");    this.sqlSessionFactory = buildSqlSessionFactory();  }  protected SqlSessionFactory buildSqlSessionFactory()    throws IOException  {    XMLConfigBuilder xmlConfigBuilder = null;    Configuration configuration;    if (this.configLocation != null) {      xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);      configuration = xmlConfigBuilder.getConfiguration();    } else {      if (logger.isDebugEnabled()) {        logger.debug("Property 'configLocation' not specified, using default MyBatis Configuration");      }      configuration = new Configuration();      configuration.setVariables(this.configurationProperties);    }    if (this.objectFactory != null) {      configuration.setObjectFactory(this.objectFactory);    }    if (this.objectWrapperFactory != null) {      configuration.setObjectWrapperFactory(this.objectWrapperFactory);    }    if (StringUtils.hasLength(this.typeAliasesPackage)) {      String[] typeAliasPackageArray = StringUtils.tokenizeToStringArray(this.typeAliasesPackage, ",; \t\n");      for (String packageToScan : typeAliasPackageArray) {            // 修改处:ThinkGem 修改实体类重名的时候抛出并打印异常,否则系统会一直递归造成无法启动            try {                configuration.getTypeAliasRegistry().registerAliases(packageToScan,                        typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);            } catch (Exception ex) {                logger.error("Scanned package: '" + packageToScan + "' for aliases", ex);                throw new NestedIOException("Scanned package: '" + packageToScan + "' for aliases", ex);            } finally {                ErrorContext.instance().reset();            }            // 修改处:ThinkGem end        if (logger.isDebugEnabled()) {          logger.debug("Scanned package: '" + packageToScan + "' for aliases");        }      }    }    if (!ObjectUtils.isEmpty(this.typeAliases)) {      for (Class typeAlias : this.typeAliases) {        configuration.getTypeAliasRegistry().registerAlias(typeAlias);        if (logger.isDebugEnabled()) {          logger.debug("Registered type alias: '" + typeAlias + "'");        }      }    }    if (!ObjectUtils.isEmpty(this.plugins)) {      for (Interceptor plugin : this.plugins) {        configuration.addInterceptor(plugin);        if (logger.isDebugEnabled()) {          logger.debug("Registered plugin: '" + plugin + "'");        }      }    }    if (StringUtils.hasLength(this.typeHandlersPackage)) {      String[] typeHandlersPackageArray = StringUtils.tokenizeToStringArray(this.typeHandlersPackage, ",; \t\n");      for (String packageToScan : typeHandlersPackageArray) {        configuration.getTypeHandlerRegistry().register(packageToScan);        if (logger.isDebugEnabled()) {          logger.debug("Scanned package: '" + packageToScan + "' for type handlers");        }      }    }    if (!ObjectUtils.isEmpty(this.typeHandlers)) {      for (TypeHandler typeHandler : this.typeHandlers) {        configuration.getTypeHandlerRegistry().register(typeHandler);        if (logger.isDebugEnabled()) {          logger.debug("Registered type handler: '" + typeHandler + "'");        }      }    }    if (xmlConfigBuilder != null) {      try {        xmlConfigBuilder.parse();        if (logger.isDebugEnabled())          logger.debug("Parsed configuration file: '" + this.configLocation + "'");      }      catch (Exception ex) {        throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);      } finally {        ErrorContext.instance().reset();      }    }    if (this.transactionFactory == null) {      this.transactionFactory = new SpringManagedTransactionFactory();    }    Environment environment = new Environment(this.environment, this.transactionFactory, this.dataSource);    configuration.setEnvironment(environment);    if (this.databaseIdProvider != null) {      try {        configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));      } catch (SQLException e) {        throw new NestedIOException("Failed getting a databaseId", e);      }    }    if (!ObjectUtils.isEmpty(this.mapperLocations)) {      for (Resource mapperLocation : this.mapperLocations) {        if (mapperLocation == null) {          continue;        }        try        {          XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), configuration, mapperLocation.toString(), configuration.getSqlFragments());          xmlMapperBuilder.parse();        } catch (Exception e) {            // 修改处:ThinkGem MapperXML有错误的时候抛出并打印异常,否则系统会一直递归造成无法启动            logger.error("Failed to parse mapping resource: '" + mapperLocation + "'", e);          throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);        } finally {          ErrorContext.instance().reset();        }        if (logger.isDebugEnabled()) {          logger.debug("Parsed mapper file: '" + mapperLocation + "'");        }      }      // 修改处:ThinkGem 启动刷新MapperXML定时器(有助于开发者调试)。      new MapperRefresh(this.mapperLocations, configuration).run();    }    else if (logger.isDebugEnabled()) {      logger.debug("Property 'mapperLocations' was not specified or no matching resources found");    }    return this.sqlSessionFactoryBuilder.build(configuration);  }  public SqlSessionFactory getObject()    throws Exception  {    if (this.sqlSessionFactory == null) {      afterPropertiesSet();    }    return this.sqlSessionFactory;  }  public Class<? extends SqlSessionFactory> getObjectType()  {    return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();  }  public boolean isSingleton()  {    return true;  }  public void onApplicationEvent(ApplicationEvent event)  {    if ((this.failFast) && ((event instanceof ContextRefreshedEvent)))    {      this.sqlSessionFactory.getConfiguration().getMappedStatementNames();    }  }}

5、接下来我们就需要把这个SqlSessionFactoryBean.java文件编译成class文件,然后再复制到mybatis-spring-1.2.2.jar包里面
重新部署你的项目 Servers > Tomcat 7.x > 右键你的项目 Remove deployment 然后再 Add Deployment…你的项目

去Tomcat 7的根目录找到对应的SqlSessionFactoryBean.class文件复制出来
这里写图片描述

这里记得检查一下编译过的class文件是否正确,将你编译好的SqlSessionFactoryBean.class文件再次拖入jd-gui.exe,看看是不是和上面写的代码对应!!!!这步很重要,我之前编译成功之后,检查发现文件都不对了,记得必须检查一下

检查无误之后,把SqlSessionFactoryBean.class复制到mybatis-spring-1.2.2.jar(是你本地项目中的jar)包中,替换原来的class文件

6、一切准备就绪,还剩下最后一个属性文件, 创建mybatis-refresh.properties文件,记得把文件格式改成UTF-8
这里写图片描述

打开文件,把下面的内容复制进去

#是否开启刷新线程enabled=true#延迟启动刷新程序的秒数delaySeconds=60  #刷新扫描间隔的时长秒数sleepSeconds=3#扫描Mapper文件的资源路径mappingPath=mapper

7、一切准备就绪,准备起飞火箭,这里需要注意,如果启动项目报错,那就把项目下咱们刚才新建的那个SqlSessionFactoryBean.java文件重命名一下,或者直接删除即可,它已经没有利用价值了

8、启动项目,然后随便修改一个mapper.xml文件,然后稍等片刻,在控制台出现如下输出,就表示你成功啦

这里写图片描述

这样就不用重启项目,也能加载到你修改的mapper.xml文件了

好了,一切都结束了,下班了,88童鞋们

这里写图片描述

1 0