1、操作系统:windows7 2、开发软件:Eclipse JavaEE Luna版本 3、数据库:MySQL,数据库管理可以使用Navicat,破解版的很容易下到,另外需要下载一个MyBatis-generator,主要是可以通过数据库的表反向生成实体类Java文件,mapper.xml文件还有对应的Dao层接口对应的Java文件,可以到我的网盘下载:http://pan.baidu.com/s/1boW1MBt 4、服务器:Tomcat7.0+ 5、JDK版本:1.7+ 6、Maven插件:根据自己习惯,选择是使用Eclipse内置的Maven还是自己重新下载Maven插件包进行集成 7、properties文件插件:主要为了防止properties文件中出现unicode的乱码,properties直接用这个插件进行编辑,也可以到我的网盘下载:http://pan.baidu.com/s/1kVq4poz下载后直接按照一般插件包的安装方式进行安装就可以了。
下面先给出我的pom.xml文件中依赖的jar包,估计下载jar要用很长时间O(∩_∩)O~,今天不早了,明天正式开始搭建。
[xml] view plain copy print ? <properties> <!-- spring版本号 --> <spring.version>4.2.5.RELEASE</spring.version> <!-- mybatis版本号 --> <mybatis.version>3.3.1</mybatis.version> <!-- springmybatis版本号 --> <springMybatis.version>1.2.2</springMybatis.version> <!-- mysql版本号 --> <mysql.version>5.1.38</mysql.version> <!-- druid 版本 --> <druid.version>1.0.18</druid.version> <!-- log4j日志管理包版本 --> <log4j.version>1.2.17</log4j.version> <!-- fastjson版本号 --> <fastjson.version>1.2.8</fastjson.version> <!-- jaksonMapper版本号 --> <jacksonMapper.version>1.9.13</jacksonMapper.version> <!-- commonsFileupload版本号 --> <commonsFileupload.version>1.3.1</commonsFileupload.version> <!-- commonsio版本号 --> <commonsio.version>2.4</commonsio.version> <!-- commoncodec版本号 --> <commonscodec.version>1.10</commonscodec.version> <!-- 提供封装好的字符串,集合等操作的工具类 --> <commonsLang.verison>2.6</commonsLang.verison> <!-- jackson-core版本号 --> <jacksonCore.version>2.7.3</jacksonCore.version> <!-- jackson-databind版本号 --> <jacksonDataBind.version>2.7.3</jacksonDataBind.version> <!-- aspectj版本号 --> <aspectj.version>1.7.2</aspectj.version> <!-- junit版本号 --> <junit.version>4.11</junit.version> </properties> <dependencies> <!-- junit 相关jar包 start --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <!-- 表示开发的时候引入,发布的时候不会加载此包 --> <scope>test</scope> </dependency> <!-- junit 相关jar包 end --> <!-- spring核心包 start --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-oxm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- spring核心包 end --> <!-- aspectj切面jar start --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <!-- aspectj切面jar end --> <!-- mybatis核心包 start --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>${mybatis.version}</version> </dependency> <!-- mybatis核心包 end --> <!-- springMybatis包 start --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>${springMybatis.version}</version> </dependency> <!-- springMybatis包 end --> <!-- mysql数据库驱动jar包 start --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <!-- mysql数据库驱动jar包 end --> <!--alibaba数据源 start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <!-- alibaba数据源 end --> <!-- log4j 日志管理包 start --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!-- log4j 日志管理包 end --> <!-- fastjson start --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <!-- fastjson end --> <!-- json映射包 start --> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>${jaksonMapper.version}</version> </dependency> <!-- json映射包 end --> <!-- 解析json用,spring-mvc.xml中的conveter依赖于此 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>${jacksonCore.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jacksonDataBind.version}</version> </dependency> <!-- 解析json用,spring-mvc.xml中的conveter依赖于此 --> <!-- 文件上传相关包 start --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>${commonsFileupload.version}</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>${commonsio.version}</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>${commonscodec.version}</version> </dependency> <!-- 文件上传相关包 end --> <!-- 提供封装好的字符串,集合等操作的工具类 start --> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>${commonsLang.verison}</version> </dependency> <!-- 提供封装好的字符串,集合等操作的工具类 end --> </dependencies>现在开始正式搭建,首先构建如下的包结构 src/main/Java下面的包: com.sdusz.framework.ssm.constant-一些定义的常量的类,反向生成得到 com.sdusz.framework.ssm.controller-控制器 com.sdusz.framework.ssm.entity-与数据库表对应的实体类 com.sdusz.framework.ssm.exception-自定义异常 com.sdusz.framework.ssm.filter-自定义过滤器 com.sdusz.framework.ssm.inteceptor-自定义拦截器 com.sdusz.framework.ssm.listener-自定义监听器 com.sdusz.framework.ssm.mapper-mybatis的dao接口层,反向生成得到 com.sdusz.framework.ssm.model-一些入参和出参对应的值对象 com.sdusz.framework.ssm.service-service层 com.sdusz.framework.ssm.serviceImpl-service实现层 com.sdusz.framework.ssm.task-定时任务相关类,可以先不建(以后再讲) com.sdusz.framework.ssm.util-自定义工具类,方便个性化操作
src/main/resources下面的文件夹: config-一些配置参数对应的文件 i18n-服务端国际化对应的properties文件 mybatis-myBatis中的.xml文件,反向生成得到 spring-spring配置文件,包括一些与spring集成的其他框架的配置文件 mybatis-generator-core-1.3.2-反向生成用的工具包,可以不放
1、在spring文件夹下建立这两个文件 spring-context.xml 就是spring容器上下文对应的配置文件,也是AOP,DI,IOC的核心文件。 spring-mvc.xml主要是就是对应了dispatcherServlet的定义,包括数据到Controller层,以及从Controller返回时的Converter。 spring-context.xml现在内容如下,现在可以什么bean和aop的定义都不写,但是一定要有这么一个结构,否则等下服务启动是会报错的,因为启动时会将配置文件中的<beans></beans>之间定义的bean进行解析,加载到BeanFactory中去,如果没有这个beans节点,无法解析,就会报错。
[xml] view plain copy print ? <?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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> </beans>spring-mvc.xml内容如下,
[xml] view plain copy print ? <?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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <!-- MVC注解扫描start --> <mvc:annotation-driven> <mvc:message-converters> <!--避免IE执行AJAX时,返回JSON出现下载文件 start--> <bean id="mappingJacksonHttpMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> </bean> <bean id="StringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!--避免IE执行AJAX时,返回JSON出现下载文件 end--> </mvc:message-converters> </mvc:annotation-driven> <!-- MVC注解扫描end --> <!-- 扫描controller包 start --> <context:component-scan base-package="com.sdusz.framework.ssm" use-default-filters="false"> <context:include-filter type="regex" expression="com.sdusz.framework.ssm.controller.*" /> </context:component-scan> <!-- 扫描controller包 end --> <!-- 使用默认servlet的处理方式处理MVC start --> <mvc:default-servlet-handler /> <!-- 使用默认servlet的处理方式处理MVC end --> <!-- 使用CGLib动态代理技术植入增强 start --> <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 使用CGLib动态代理技术植入增强 end --> </beans>在web.xml中添加如下配置,其中: contextConfigLocation为类路径下的,也就是src/main/resurces下的spring/spring-context.xml文件,不配置将会默认去找WEB-INF下的applicationContext.xrnl 文件,找不到就会报错,log4j配置文件的位置同理,这里就不给出log4j的具体配置了,因为因项目而异,配置没有通用性。
[xml] view plain copy print ? <!-- 首页 start --> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- 首页 end --> <!-- 上下文初始化参数 start --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-context.xml</param-value> </context-param> <!-- 上下文初始化参数 end --> <!-- log4j配置文件路径 start --> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:config/log4j.properties</param-value> </context-param> <!-- log4j配置文件路径 end --> <!-- log4j刷新周期 start --> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>600000</param-value> </context-param> <!-- log4j刷新周期 end --> <!-- 项目根目录名称 start --> <context-param> <param-name>webAppRootKey</param-name> <param-value>ssm.root</param-value> </context-param> <!-- 项目根目录名称 end --> <!-- spring全站编码过滤器 start --> <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> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring全站编码过滤器 end --> <!-- log4j监听器 start --> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <!-- log4j监听器 end --> <!-- Spring上下文初始化监听器 start --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring上下文初始化监听器 end --> <!-- 防止Spring内存溢出监听器 start --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!-- 防止Spring内存溢出监听器 end --> <!-- SpringMVC servlet start --> <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/spring-mvc.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/interfaces/*</url-pattern> </servlet-mapping> <!-- SpringMVC servlet end --> <!-- session过期时间 start --> <session-config> <session-timeout>30</session-timeout> </session-config> <!-- session过期时间 end -->在com.sdusz.framework.ssm.controller包下添加一个测试类TestController.java
[java] view plain copy print ? @Controller @RequestMapping("test") public class TestController { /** * 方法描述: 返回单个字符串 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:22:08 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * String 返回的字符串 */ @RequestMapping("/m001") @ResponseBody public String getString() { return "hello,这只是一个字符串!"; } /** * 方法描述: 返回map对象 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:21:37 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * Map<String,String> 返回的map对象 */ @RequestMapping("/m002") @ResponseBody public Map<String, String> getJSON() { Map<String, String> data = new HashMap<String, String>(); data.put("id", "001"); data.put("name", "张三"); return data; } } /** * 方法描述: 访问restful接口并将参数作为结果返回 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:22:40 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param clientType * 对应{clientType} * @param loginId * 对应{loginId} * @param userType * 对应{userType} * @return * Map<String,String> 参数组装出的map对象 */ @RequestMapping("/{clientType}/{loginId}/{userType}/m003") @ResponseBody public Map<String, String> testRestful(@PathVariable String clientType, @PathVariable String loginId, @PathVariable String userType) { Map<String, String> data = new HashMap<String, String>(); data.put("clientType", clientType); data.put("loginid", loginId); data.put("userType", userType); return data; } /** * 方法描述: 测试将model转为json传到前台</br> * 初始作者: shenmengqi * 创建日期: 2016年3月28日-下午10:12:47 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param models * 传入model * @return * Object json对象 */ @RequestMapping("/m005") @ResponseBody public Object testParamList(@RequestBody List<VoModel> models) { return JSON.toJSON(models); }这里边的接口的返回值类型任意,另外方法上需要加上@ResponseBody注解,由于在spring-mvc.xml中配置了Converter,其实最终返回给前台的结果都是json对象,contentType就是application/json;charset=utf-8,但是如果要从前台传入VO就必须将对象用JSON.stringify()进行转换,类前面要加@Controller注解。上面接口的访问路径依次为: 1.http://ip:port/工程名/interfaces/test/m001 参数:无 请求类型:任意 结果:hello,这只是一个字符串! 2.http://ip:port/工程名/interfaces/test/m002 参数:无 请求类型:任意 结果:{“name”:”张三”,”id”:”001”} 3.http://ip:port/工程名/interfaces/test/1/2/3/m003 参数:无 请求类型:任意 结果:{“clientType”:”1”,”loginid”:”2”,”userType”:”3”} 4.http://ip:port/工程名/interfaces/test/m005 参数:参数的结构要与@RequestBody的结构一致,key必须与javabean的属性对应,
[{ "id":"001", "name":"name" }]请求类型:POST 结果:
[ { "name": "name", "id": "001", "voModel2": null, "email": null } ]如果上述几个接口都可以调用成功,且没有乱码出现,那么Spring与SpringMVC就已经整合成功了!
之前spring和SpringMVC已经整合成功了,现在开始整合MyBatis。 先在数据库中创建emp表:
[sql] view plain copy print ? DROP TABLE IF EXISTS `emp`; CREATE TABLE `emp` ( `id` varchar(64) NOT NULL, `name` varchar(100) NOT NULL, `age` int(11) DEFAULT NULL, `gender` int(11) DEFAULT NULL, `birthday` datetime DEFAULT NULL, `hiredate` datetime DEFAULT NULL, `job` varchar(10) DEFAULT NULL, `hobbies` varchar(200) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;在之前的spring-context.xml开始添加配置 1、配置注解扫描,扫描service包下的注解,主要是为了之后可以将@Service注解的类注入到Controller层进行使用
[xml] view plain copy print ? <!-- 开启注解扫描 start --> <context:annotation-config /> <context:component-scan base-package="com.sdusz.framework.ssm" use-default-filters="false"> <context:include-filter type="regex" expression="com.sdusz.framework.ssm.service*.*" /> </context:component-scan> <!-- 开启注解扫描 end -->2、配置读取properties的bean,读取到的所有properties配置文件中的所有键值对,之后要用到其中的值只需要${key}即可使用
[xml] view plain copy print ? <!-- 加载properties配置文件 start --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:config/jdbc.properties</value> </list> </property> <!-- <property name="ignoreUnresolvablePlaceholders" value="true" /> --> </bean> <!-- 加载properties配置文件 end -->3、配置数据源:这里我选择使用阿里的druid数据源,第一安全性高,第二异常的处理比其他数据源更为强大,第三由于阿里公司的业务偏向大数据,数据源设计自然也吸取了大数据高并发的一些理念进行设计,而且经过前人实践证明,执行效率确实是目前主流数据源中最高的。
[xml] view plain copy print ? <!-- 配置druid数据源 start --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="filters" value="${jdbc.filters}" /> <property name="maxActive" value="${jdbc.maxActive}" /> <property name="initialSize" value="${jdbc.initialSize}" /> <property name="maxWait" value="${jdbc.maxWait}" /> <property name="minIdle" value="${jdbc.minIdle}" /> <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${jdbc.validationQuery}" /> <property name="testWhileIdle" value="${jdbc.testWhileIdle}" /> <property name="testOnBorrow" value="${jdbc.testOnBorrow}" /> <property name="testOnReturn" value="${jdbc.testOnReturn}" /> <property name="poolPreparedStatements" value="${jdbc.poolPreparedStatements}" /> <property name="maxOpenPreparedStatements" value="${jdbc.maxOpenPreparedStatements}" /> <property name="removeAbandoned" value="${jdbc.removeAbandoned}" /> <property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}" /> <property name="logAbandoned" value="${jdbc.logAbandoned}" /> </bean> <!-- 配置druid数据源 end -->上面的bean中property对应的值,就是从jdbc.properties配置文件中读取的,jdbc.properties配置文件的内容如下:
[xml] view plain copy print ? ####druid数据源配置 #链接字符串 jdbc.url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8 #数据库驱动类名 jdbc.driverClassName=com.mysql.jdbc.Driver #用户名 jdbc.username=root #密码 jdbc.password=root #属性类型是字符串,通过别名的方式配置扩展插件,常用的插件有:监控统计用的filter:stat 日志用的filter:log4j 防御sql注入的filter:wall jdbc.filters=stat #最大连接池数量 jdbc.maxActive=20 #初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时 jdbc.initialSize=10 #获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配useUnfairLock属性为true使用非公平锁。 jdbc.maxWait=60000 #最小连接池数量 jdbc.minIdle=10 #有两个含义:1) Destroy线程会检测连接的间隔时间2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明 jdbc.timeBetweenEvictionRunsMillis=60000 #一个连接在池中最小生存的时间,单位是毫秒 jdbc.minEvictableIdleTimeMillis=300000 #用来检测连接是否有效的sql,要求是一个查询语句。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会其作用。 jdbc.validationQuery=SELECT 'x' #建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 jdbc.testWhileIdle=true #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 jdbc.testOnBorrow=false #归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能 jdbc.testOnReturn=false #在Druid中,不会存在Oracle下PSCache占用内存过多的问题,可以把这个数值配置大一些,比如说100 jdbc.maxOpenPreparedStatements=20 #是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启。要启用PSCache,必须配置大于0,当大于0时,poolPreparedStatements自动触发修改为true。 jdbc.poolPreparedStatements=true #打开removeAbandoned功能 jdbc.removeAbandoned=true #1800秒,也就是30分钟 jdbc.removeAbandonedTimeout=1800 #关闭abanded连接时输出错误日志 jdbc.logAbandoned=true4、配置MyBatis的SqlSssionFactory,mapperLocations配置为扫描src/main/mybatis目录下的所有.xml文件,就是所有的MyBatis的mapper.xml文件,另外设置mybatis的全局配置文件路径,这个可以不用配置,这样就使用默认配置。
[xml] view plain copy print ? <!-- 配置sqlSessionFactory start--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 自动扫描mapper文件 --> <property name="mapperLocations" value="classpath:mybatis/*.xml"></property> <!-- mybatis全局配置文件 --> <property name="configLocation" value="classpath:config/mybatis-config.xml"></property> </bean> <!-- 配置sqlSessionFactory end-->mybatis-config.xml文件内容如下:
[xml] view plain copy print ? <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0 //EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <settings> <!-- 配置全局性 cache 的 ( 开 / 关) default:true --> <setting name="cacheEnabled" value="false"/> <!-- 是否使用 懒加载 关联对象同 hibernate中的延迟加载 一样default:true --> <!-- <setting name="lazyLoadingEnabled" value="true"/> --> <!-- [当对象使用延迟加载时 属性的加载取决于能被引用到的那些延迟属性,否则,按需加载(需要的是时候才去加载)] --> <setting name="aggressiveLazyLoading" value="true"/> <!-- 是否允许单条sql 返回多个数据集(取决于驱动的兼容性) default:true --> <setting name="multipleResultSetsEnabled" value="true"/> <!-- 是否可以使用列的别名 (取决于驱动的兼容性) default:true--> <setting name="useColumnLabel" value="true"/> <!--允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。default:false--> <setting name="useGeneratedKeys" value="false"/> <!--指定 MyBatis 如何自动映射 数据基表的列 NONE:不隐射 PARTIAL:部分FULL:全部--> <setting name="autoMappingBehavior" value="PARTIAL"/> <!-- 这是默认的执行类型 SIMPLE :简单 REUSE:执行器可能重复使用prepared statements 语句 BATCH:执行器可以重复执行语句和批量更新 --> <setting name="defaultExecutorType" value="SIMPLE"/> <!-- 设置驱动等待数据响应的超时数默认没有设置--> <setting name="defaultStatementTimeout" value="25000"/> <!--是否启用 行内嵌套语句defaut:false--> <setting name="safeRowBoundsEnabled" value="false"/> <!-- [是否 启用数据中 A_column 自动映射 到 java类中驼峰命名的属性 default:fasle] --> <setting name="mapUnderscoreToCamelCase" value="false"/> <!-- 设置本地缓存范围 session:就会有数据的共享statement:语句范围 (这样就不会有数据的共享 ) defalut:session --> <setting name="localCacheScope" value="SESSION"/> <!-- 设置但JDBC类型为空时,某些驱动程序 要指定值,default:OTHER --> <setting name="jdbcTypeForNull" value="NULL"/> <!-- 设置触发延迟加载的方法--> <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> </settings> </configuration>5、配置扫描dao接口所在的包
[xml] view plain copy print ? <!-- 扫描Dao接口所在的包名 start --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.sdusz.framework.ssm.mapper" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property> </bean> <!-- 扫描Dao接口所在的包名 end -->6、配置JdbcTemplate,本来集成了mybatis,为何还要jdbcTemplate呢?原因是mybatis的批量处理效率不高,而且不同数据库,写法也略有差异,使用更接近底层jdbc的jdbcTemplate进行批量操作,可以提升性能。
[xml] view plain copy print ? <!-- jdbcTemplate start --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg name="dataSource" ref="dataSource"/> </bean> <!-- jdbcTemplate end -->7、配置数据源事务切面,进行事务管理,我将事务的回滚配置在service层,对于异常,进行回滚,如果有异常,不要捕获,直接网上抛,到时用一个统一的拦截器进行处理即可,对于需要用事务进行控制的方法,方法的命名一定要以下面事务切面中给出的前缀命名,当然,也可自己添加其它的。
[xml] view plain copy print ? <!-- 数据源事务管理器start --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 数据源事务管理器end --> <!-- 事务切面 start--> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="get*" propagation="REQUIRED" read-only="true" /> <tx:method name="count*" propagation="REQUIRED" read-only="true" /> <tx:method name="find*" propagation="REQUIRED" read-only="true" /> <tx:method name="list*" propagation="REQUIRED" read-only="true" /> <tx:method name="search*" propagation="REQUIRED" read-only="true" /> <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="modify*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <tx:method name="edit*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> <!-- 批量操作最好用jdbcTemplate --> <tx:method name="batch*" propagation="REQUIRED" rollback-for="java.lang.Exception"/> </tx:attributes> </tx:advice> <!-- 事务切面 end --> <!-- 事务aop切入点 start--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.sdusz.framework.ssm.service.*.*(..)) " /> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" /> </aop:config> <!-- 事务aop切入点 end-->1、在com.sdusz.framework.ssm.entity添加反向生成的Emp.Java类,对应数据库中的EMP表
[java] view plain copy print ? package com.sdusz.framework.ssm.entity; import java.io.Serializable; import java.util.Date; import com.alibaba.fastjson.JSON; /** * 文件名称: com.sdusz.framework.ssm.entity.Emp.java * 初始作者: shenmengqi * 创建日期: 2016年3月18日 * 功能说明: 测试实体-员工实体类 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * Copyright (c) 2010-2011 .All rights reserved. */ public class Emp implements Serializable { /** * 序列化版本号 */ private static final long serialVersionUID = 1L; /** * 实体对应的数据库表名 */ public static final String TABLE_NAME = "emp"; /** * id */ private String id; /** * 姓名 */ private String name; /** * 年龄 */ private Integer age; /** * 性别 */ private Integer gender; /** * 生日 */ private Date birthday; /** * 入职日期 */ private Date hiredate; /** * 工作 */ private String job; /** * 爱好 */ private String hobbies; /** * 方法描述: 获取年龄 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:31:17 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * Integer 年龄 */ public Integer getAge() { return age; } /** * 方法描述: 获取生日 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:31:40 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * Date 生日 */ public Date getBirthday() { return birthday; } /** * 方法描述: 获取性别 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:31:57 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * Integer 性别 */ public Integer getGender() { return gender; } /** * 方法描述: 获取入职日期 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:32:17 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * Date 入职日期 */ public Date getHiredate() { return hiredate; } /** * 方法描述: 获取爱好 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:32:37 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * String 爱好 */ public String getHobbies() { return hobbies; } /** * 方法描述: 获取id * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:33:02 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * String id */ public String getId() { return id; } /** * 方法描述: 获取工作 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:33:20 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * String 工作 */ public String getJob() { return job; } /** * 方法描述: 获取姓名 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:33:37 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return * String 姓名 */ public String getName() { return name; } /** * 方法描述: 设置年龄 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:33:54 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param age * 年龄 */ public void setAge(Integer age) { this.age = age; } /** * 方法描述: 设置生日 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:34:09 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param birthday * 生日 */ public void setBirthday(Date birthday) { this.birthday = birthday; } /** * 方法描述: 设置性别 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:34:30 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param gender * 性别 */ public void setGender(Integer gender) { this.gender = gender; } /** * 方法描述: 设置入职日期 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:34:56 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param hiredate * 入职日期 */ public void setHiredate(Date hiredate) { this.hiredate = hiredate; } /** * 方法描述: 设置爱好 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:35:16 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param hobbies * 爱好 */ public void setHobbies(String hobbies) { this.hobbies = hobbies; } /** * 方法描述: 设置id * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:35:37 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param id * id */ public void setId(String id) { this.id = id; } /** * 方法描述: 设置工作 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:35:53 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param job * 工作 */ public void setJob(String job) { this.job = job; } /** * 方法描述: 设置姓名 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:36:10 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param name * 姓名 */ public void setName(String name) { this.name = name; } /** * 方法描述: 重写toString()方法 * 初始作者: shenmengqi * 创建日期: 2016年3月22日-下午2:14:07 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ */ @Override public String toString() { return JSON.toJSONString(this); } }2、com.sdusz.framework.ssm.mapper添加反向生成的EmpMapper.java类,删去其中的默认方法,添加自己需要的方法
[java] view plain copy print ? package com.sdusz.framework.ssm.mapper; import org.apache.ibatis.annotations.Param; import com.sdusz.framework.ssm.entity.Emp; /** * 文件名称: com.sdusz.framework.ssm.mapper.EmpMapper.java * 初始作者: shenmengqi * 创建日期: 2016年3月18日 * 功能说明: 员工mapper * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * Copyright (c) 2010-2011 .All rights reserved. */ public interface EmpMapper { /** * 方法描述: 通过id获取员工信息 * 初始作者: shenmengqi * 创建日期: 2016年3月17日-下午1:45:04 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param id * 主键 * @return * Emp 员工实体 */ Emp selectEmpById(@Param("id") String id); }3、在src/main/resources下的mybatis目录下添加反向生成的EmpMapper.xml文件,删除其中的无用内容,添加自己的语句,对应每个语句的id即为EmpMapper.java中每个方法的方法名
[xml] view plain copy print ? <?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" > <!-- 员工mapper --> <mapper namespace="com.sdusz.framework.ssm.mapper.EmpMapper" > <!-- 通过id获取员工信息--> <select id="selectEmpById" parameterType="java.lang.String" resultType="com.sdusz.framework.ssm.entity.Emp"> select * from emp where id=#{id,jdbcType=BIGINT} </select> </mapper>4、com.sdusz.framework.ssm.service添加EmpService.java接口
[java] view plain copy print ? package com.sdusz.framework.ssm.service; import com.sdusz.framework.ssm.entity.Emp; /** * 文件名称: com.sdusz.framework.ssm.service.EmpService.java * 初始作者: shenmengqi * 创建日期: 2016年3月18日 * 功能说明: 员工service * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * Copyright (c) 2010-2011 .All rights reserved. */ public interface EmpService { /** * 方法描述: 批量添加员工信息,用jdbc,另一方面为了测试事务的有效性 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:49:09 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return int * 插入成功的数量 * @throws Exception * 异常 */ int batchAddEmp() throws Exception; /** * 方法描述: 通过id获取员工信息 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:49:55 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param id * 员工id * @return * Emp 员工实体 */ Emp getEmpById(String id); }5、com.sdusz.framework.ssm.serviceImpl添加EmpServiceImpl.java类,实现EmpService接口,对于JdbcTemplate还有EmpMapper直接使用@Autowired进行注入,第二个方法直接通过id获取员工信息,第一个方法使用JdbcTemplate批量插入员工信息(这里我没用批量插入的api,为了观察更清晰,用循环进行插入,看某一条出错,其余是否会回滚),顺便可以测试异常事务切面异常情况是否会进行回滚
[java] view plain copy print ? package com.sdusz.framework.ssm.serviceImpl; import java.util.Date; import java.util.Random; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; import org.springframework.jdbc.core.JdbcTemplate; import com.sdusz.framework.ssm.entity.Emp; import com.sdusz.framework.ssm.mapper.EmpMapper; import com.sdusz.framework.ssm.service.EmpService; import com.sdusz.framework.ssm.util.UUIDUtils; /** * 文件名称: com.sdusz.framework.ssm.serviceImpl.EmpServiceImpl.java * 初始作者: shenmengqi * 创建日期: 2016年3月18日 * 功能说明: 员工service实现类 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * Copyright (c) 2010-2011 .All rights reserved. */ public class EmpServiceImpl implements EmpService { /** * log4j日志对象 */ private static final Logger log = Logger.getLogger(EmpServiceImpl.class); /** * 员工mapper */ @Autowired private EmpMapper empMapper; /** * jdbcTemplate */ @Autowired private JdbcTemplate jdbcTemplate; /** * 方法描述: 用jdbcTemplate循环插入员工信息,一方面测试jdbcTemplate,另一方面测试事务有效性 * 初始作者: shenmengqi * 创建日期: 2016年3月17日-下午2:03:11 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @throws Exception * 异常对象 */ @Override public int batchAddEmp() throws Exception { int r = 0; for (int i = 0; i < new Random().nextInt(5); i++) { // log.info("开始插入第" + (i + 1) + "条"); Emp e = new Emp(); e.setId(UUIDUtils.get32UUID()); e.setName("name" + i); e.setJob("job" + i); e.setHobbies("hobbies" + i); e.setGender(new Random().nextInt(1)); e.setAge(new Random().nextInt(30)); e.setBirthday(new Date()); e.setHiredate(new Date()); // if (i == 7) { // log.error("出错了,回滚!"); // throw new Exception("出错了!"); // } int rr = jdbcTemplate.update("insert into emp values(?,?,?,?,?,?,?,?)", new Object[] { e.getId(), e.getName(), e.getAge(), e.getGender(), e.getBirthday(), e.getHiredate(), e.getJob(), e.getHobbies() }); if (rr == 1) { r++; } // log.info("第" + (i + 1) + "条插入成功"); } return r; } /** * 方法描述: 通过id获取员工信息,有缓存 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:51:55 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ */ @Override @Cacheable(value = "empCache", key = "#id+'~cache'", condition = "#id=='1406'") public Emp getEmpById(String id) { System.out.println("调用了getEmpById() 方法"); return empMapper.selectEmpById(id); } }6、com.sdusz.framework.ssm.controller中添加EmpController.java类,EmpService使用@Resource进行注入,一般Controller层只是一个负责转发的层,所以,业务逻辑能在Service层处理就尽量在Service层处理,每一层必要的日志记录也是需要的。Controller遇到异常也不要捕获,向上抛出由统一的异常拦截器进行处理。
[java] view plain copy print ? package com.sdusz.framework.ssm.controller; import javax.annotation.Resource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import com.sdusz.framework.ssm.entity.Emp; import com.sdusz.framework.ssm.service.EmpService; /** * 文件名称: com.sdusz.framework.ssm.controller.EmpController.java * 初始作者: shenmengqi * 创建日期: 2016年3月18日 * 功能说明: 测试类,员工信息控制器 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * Copyright (c) 2010-2011 .All rights reserved. */ @Controller @RequestMapping("emp") public class EmpController { /** * 员工信息service */ @Resource private EmpService empService; /** * 方法描述: 批量添加员工信息 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:18:35 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @return int * 插入成功的记录数 * @throws Exception * 异常 */ @RequestMapping("/addEmps") @ResponseBody public int addEmps() throws Exception { return empService.batchAddEmp(); } /** * 方法描述: 通过id获取员工信息 * 初始作者: shenmengqi * 创建日期: 2016年3月18日-上午9:20:10 * 开始版本: 2.0.0 * ================================================= * 修改记录: * 修改作者 日期 修改内容 * ================================================ * * @param id * 员工id * @return * Emp 员工实体 */ @RequestMapping("/getEmpById") @ResponseBody public Emp getEmpById(@RequestParam String id) { return empService.getEmpById(id); } }7、依次访问上面两个接口 http://ip:port/工程名/interfaces/emp/addEmps 先访问,如果批量插入成功返回影响的行数则表示jdbcTemplate可用 修改service实现类代码,制造异常,再测试,看是否回滚成功 http://ip:port/工程名/interfaces/emp/getEmpById?id=1406 直接返回员工信息json对象,则表示成功
至此就完成了一个简单Spring+SpringMVC+MyBatis框架的搭建,其实在真正的企业级开发中,做了这些是远远不够的,接下来我还要在这个框架中融入其他的东西!
