SpringMVC+Mybatis+热部署mapper文件
来源:互联网 发布:优化蜜蜡能买吗 编辑:程序博客网 时间:2024/05/15 03:31
SpringMVC+Mybatis+热部署mapper文件
每天都是从网上找别人分享出来的好东西纳入囊中,今天自己也想分享一下自己的一些东西给大家。
一直在用SSH框架,没办法现在的主流就是SpringMvc+Mybatis,所以也研究了一下。看了几天网上分享的精髓,恕小弟我愚昧,搞了好久才弄明白其中的奥妙,不过我觉得自己懂了还不够深刻,必须拿出来和大家分享,让大家也能看懂才是真正的懂了。
我尽量写的简单点通俗易懂,只要是有点java基础就能看懂这篇文章是我的目标。
我们老大最近让了解markDown,写标题的时候正好看到有‘切换markDown编辑器’,直接开干,之前真的一点也不了解markDown。
(奥利给,我次有内,为给呀,老铁没毛病,今天又是一个楼面,100来平方,轻松拿下,干就完了!!)不要问我这句话啥意思,最近快手上有个雷哥,因这句口头禅火了。废话是不是有点太多了?好吧,我错了步入正题!!!
我发现一个问题,也可能是我自己的问题,就是在看别人分享出来的资源的时候,总是跟着资源一步一步做,然后突然卡壳,要不就是报错要不就是各种纠结,瞬间继续看下去的心情就没了,这里建议大家耐心点,哪里卡壳了,就好好研究一下,当你迈过这个坎后,你肯定会收获更多
开发工具
Myeclipse2014,jdk1.7,tomcat7,数据库我用的是oracle,伙计们这几个东西都先给我准备好了,马上开始打仗了。什么?这些东西你都不知道?用我们老家的口头禅来说“外日他dei儿,你给我去求吧”,这是作为一个程序员必须知道的,就像你打仗需要用枪一个道理!
愤怒感言
每次跟着网上的资料学习,都会被一大堆的各种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童鞋们
- SpringMVC+Mybatis+热部署mapper文件
- mybatis热部署加载*Mapper.xml文件
- mybatis实现mapper文件热部署
- mybatis实现mapper文件热部署
- mybatis实现mapper文件热部署
- mybatis热部署加载*Mapper.xml文件,手动刷新*Mapper.xml文件
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- 实现MyBatis Mapper XML文件增量动态刷新,自动加载,热加载,热部署
- Mybatis热加载Mapper.xml
- Mybatis - Mapper文件简练
- MyBatis Mapper 文件例子
- 【SpringMVC+mybatis】6.mybatis mapper代理方法
- Springmvc+mybatis+easyui 构造方法和mapper
- springmvc-mybatis 之mapper代理开发
- MyBatis Mapper XML 文件 01
- Nginx主配置参数详解,Nginx配置网站
- LAMP(ftp)环境搭建
- Sql语句中的as问题
- iOS从零基础到精通就业-C语言入门 4分支结构if
- MindManager中该如何实现换行
- SpringMVC+Mybatis+热部署mapper文件
- BCMath 任意精度数学
- 第16周项目1-验证算法(4)快速排序 以中间位置的元素作为基准
- redhat6.4 安装codeblocks
- 多个jar包合并成一个jar包(ant)
- laravel学习第一步--学习建议--初探
- package.json字段全解
- Mac配置环境变量
- ARM仿真调试技术