1、基本概念
ssm:spring+springMVC+mybatis
2、开发环境
Eclipse mars + jdk1.7 + maven + tomcat7
3、使用maven构建web项目
3.1、首先,创建一个maven object
3.2、创建一个新的路径、next
3.3、选择 maven-archetype-webapp next
3.4 输入artifact id 这个是项目的唯一标识 实际对应项目的名称 group id一般是公司,组织的名称反写,groupid+artifactid就保证了一个项目的唯一性。
4.1、在pom.xml文件中引入jar包,各个包是干嘛的 都有说明,此处不在赘述。
1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 3 <modelVersion>4.0.0</modelVersion> 4 <groupId>com.hbst.www</groupId> 5 <artifactId>BaseSsm_3</artifactId> 6 <packaging>war</packaging> 7 <version>0.0.1-SNAPSHOT</version> 8 <name>BaseSsm_3 Maven Webapp</name> 9 <url>http://maven.apache.org</url> 10 <properties> 11 <!-- spring版本号 --> 12 <spring.version>4.0.2.RELEASE</spring.version> 13 <!-- mybatis版本号 --> 14 <mybatis.version>3.2.6</mybatis.version> 15 <!-- log4j日志文件管理包版本 --> 16 <slf4j.version>1.7.7</slf4j.version> 17 <log4j.version>1.2.17</log4j.version> 18 </properties> 19 20 21 <dependencies> 22 <dependency> 23 <groupId>junit</groupId> 24 <artifactId>junit</artifactId> 25 <version>3.8.1</version> 26 <scope>test</scope> 27 </dependency> 28 29 <!-- spring核心包 --> 30 <dependency> 31 <groupId>org.springframework</groupId> 32 <artifactId>spring-core</artifactId> 33 <version>${spring.version}</version> 34 </dependency> 35 36 <dependency> 37 <groupId>org.springframework</groupId> 38 <artifactId>spring-web</artifactId> 39 <version>${spring.version}</version> 40 </dependency> 41 <dependency> 42 <groupId>org.springframework</groupId> 43 <artifactId>spring-oxm</artifactId> 44 <version>${spring.version}</version> 45 </dependency> 46 <dependency> 47 <groupId>org.springframework</groupId> 48 <artifactId>spring-tx</artifactId> 49 <version>${spring.version}</version> 50 </dependency> 51 52 <dependency> 53 <groupId>org.springframework</groupId> 54 <artifactId>spring-jdbc</artifactId> 55 <version>${spring.version}</version> 56 </dependency> 57 58 <dependency> 59 <groupId>org.springframework</groupId> 60 <artifactId>spring-webmvc</artifactId> 61 <version>${spring.version}</version> 62 </dependency> 63 <dependency> 64 <groupId>org.springframework</groupId> 65 <artifactId>spring-aop</artifactId> 66 <version>${spring.version}</version> 67 </dependency> 68 69 <dependency> 70 <groupId>org.springframework</groupId> 71 <artifactId>spring-context-support</artifactId> 72 <version>${spring.version}</version> 73 </dependency> 74 75 <dependency> 76 <groupId>org.springframework</groupId> 77 <artifactId>spring-test</artifactId> 78 <version>${spring.version}</version> 79 </dependency> 80 <!-- mybatis核心包 --> 81 <dependency> 82 <groupId>org.mybatis</groupId> 83 <artifactId>mybatis</artifactId> 84 <version>${mybatis.version}</version> 85 </dependency> 86 <!-- mybatis/spring包 --> 87 <dependency> 88 <groupId>org.mybatis</groupId> 89 <artifactId>mybatis-spring</artifactId> 90 <version>1.2.2</version> 91 </dependency> 92 93 <!-- 导入java ee jar 包 --> 94 <dependency> 95 <groupId>javax</groupId> 96 <artifactId>javaee-api</artifactId> 97 <version>7.0</version> 98 </dependency> 99 100 <!-- 导入Mysql数据库链接jar包 --> 101 <dependency> 102 <groupId>mysql</groupId> 103 <artifactId>mysql-connector-java</artifactId> 104 <version>5.1.36</version> 105 </dependency> 106 <!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 --> 107 <dependency> 108 <groupId>commons-dbcp</groupId> 109 <artifactId>commons-dbcp</artifactId> 110 <version>1.2.2</version> 111 </dependency> 112 113 <!-- JSTL标签类 --> 114 <dependency> 115 <groupId>jstl</groupId> 116 <artifactId>jstl</artifactId> 117 <version>1.2</version> 118 </dependency> 119 <!-- 日志文件管理包 --> 120 <!-- log start --> 121 <dependency> 122 <groupId>log4j</groupId> 123 <artifactId>log4j</artifactId> 124 <version>${log4j.version}</version> 125 </dependency> 126 127 128 <!-- servlet api --> 129 <dependency> 130 <groupId>javax.servlet</groupId> 131 <artifactId>javax.servlet-api</artifactId> 132 <version>3.0.1</version> 133 <scope>provided</scope> 134 </dependency> 135 136 <!-- 格式化对象,方便输出日志 --> 137 <dependency> 138 <groupId>com.alibaba</groupId> 139 <artifactId>fastjson</artifactId> 140 <version>1.1.41</version> 141 </dependency> 142 143 144 <dependency> 145 <groupId>org.slf4j</groupId> 146 <artifactId>slf4j-api</artifactId> 147 <version>${slf4j.version}</version> 148 </dependency> 149 150 <dependency> 151 <groupId>org.slf4j</groupId> 152 <artifactId>slf4j-log4j12</artifactId> 153 <version>${slf4j.version}</version> 154 </dependency> 155 <!-- log end --> 156 <!-- 映入JSON --> 157 <dependency> 158 <groupId>org.codehaus.jackson</groupId> 159 <artifactId>jackson-mapper-asl</artifactId> 160 <version>1.9.13</version> 161 </dependency> 162 <!-- 上传组件包 --> 163 <dependency> 164 <groupId>commons-fileupload</groupId> 165 <artifactId>commons-fileupload</artifactId> 166 <version>1.3.1</version> 167 </dependency> 168 <dependency> 169 <groupId>commons-io</groupId> 170 <artifactId>commons-io</artifactId> 171 <version>2.4</version> 172 </dependency> 173 <dependency> 174 <groupId>commons-codec</groupId> 175 <artifactId>commons-codec</artifactId> 176 <version>1.9</version> 177 </dependency> 178 </dependencies> 179 <build> 180 <finalName>BaseSsm_3</finalName> 181 </build> 182 </project>
4.2、Spring与MyBatis的整合
此次整合,并没有使用mapper接口 而是使用sqlSessionTemplate接口来实现,使用mapper接口开发,会对每张表分别生成一个model,dao和一个mapper.xml,造成文件数过多。
4.2.1、SqlSessionTemplate
SqlSessionTemplate是MyBatis-spring的核心。这个类负责管理MyBatis的SqlSession,调用MyBatis的SQL方法。SqlSessionTemplate是线程安全的,可以被多个DAO所共享使用。
当调用SQL方法时,包含从映射器getMapper()方法返回的方法,SqlSessionTemplate将会保证使用的SqlSession是和当前Spring的事务相关的。此外,它管理session的生命周期,包含必要的关闭,提交或回滚操作。
SqlSessionTemplate实现了SqlSession,这就是说要对MyBatis的SqlSession进行简易替换。
SqlSessionTemplate通常是被用来替代默认的MyBatis实现的DefaultSqlSession,因为它不能参与到Spring的事务中也不能被注入,因为它是线程不安全的。相同应用程序中两个类之间的转换可能会引起数据一致性的问题。
SqlSessionTemplate对象可以使用SqlSessionFactory作为构造方法的参数来创建。
4.2.2、介绍完基本概念,现在开始正式整合,首先创建jdbc.propreties文件 (文件编码修改为 utf-8 )
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/db3
jdbc.username=root
jdbc.password=123456
jdbc.minIdle=30
jdbc.maxIdle=80
jdbc.maxWait=60000
jdbc.maxActive=80
jdbc.initialSize=20
jdbc.testWhileIdle=true
jdbc.testOnBorrow=false
jdbc.testOnReturn=false
jdbc.validationQuery=select 1
jdbc.validationQueryTimeout=1
jdbc.timeBetweenEvictionRunsMillis=600000
jdbc.numTestsPerEvictionRun=40
4.2.3、建立spring-mybatis.xml配置文件
这个文件就是用来完成spring和mybatis的整合的。这里面也没多少行配置,主要的就是 自动扫描,自动注入,配置数据库 。
<?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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- 自动扫描 --> <context:component-scan base-package="com.hbst.basessm_3" /> <!-- proxy-target-class="true"强制使用CGLib代理,为false则spring会自动选择 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <!-- 引入jdbc配置文件 --> <context:property-placeholder location="classpath:config/jdbc/jdbc.properties" /> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <!-- 队列中的最小等待数 --> <property name="minIdle" value="${jdbc.minIdle}"></property> <!-- 队列中的最大等待数 --> <property name="maxIdle" value="${jdbc.maxIdle}"></property> <!-- 最长等待时间,单位毫秒 --> <property name="maxWait" value="${jdbc.maxWait}"></property> <!-- 最大活跃数 --> <property name="maxActive" value="${jdbc.maxActive}"></property> <property name="initialSize" value="${jdbc.initialSize}"></property> <property name="testWhileIdle" value="${jdbc.testWhileIdle}"></property> <property name="testOnBorrow" value="${jdbc.testOnBorrow}"></property> <property name="testOnReturn" value="${jdbc.testOnReturn}"></property> <property name="validationQuery" value="${jdbc.validationQuery}" /> <property name="validationQueryTimeout" value="${jdbc.validationQueryTimeout}"></property> <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"></property> <property name="numTestsPerEvictionRun" value="${jdbc.numTestsPerEvictionRun}"></property> </bean> <!-- 配置MyBitas SqlSessionFactoryBean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="configLocation" value="classpath:config/mybatis/typeAliasMapper.xml" /> <property name="mapperLocations" value="classpath:config/mybatis/mappers/*/*Mapper.xml" /> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置SqlSessionTemplate --> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype"> <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" /> </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/cn/hnust/mapping/*.xml"></property> --> <!-- </bean> --> <!-- DAO接口所在包名,Spring会自动查找其下的类 --> <!-- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> --> <!-- <property name="basePackage" value="com.cn.hnust.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> <!-- 使用注解的方式配置事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> </beans>
4.2.4、我在上面配置 SqlSessionTemplate 的时候 指定了一个 typeAliasMapper.xml,这个文件用来配置实体别名,下面我们来创建它,他指定了一个分页拦截插件,代码会贴在最后,这里不再给出
<?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> <typeAliases> <typeAlias alias="user" type="com.hbst.basessm_3.pojo.User"/> </typeAliases> <!-- mybatis 分页拦截 --> <plugins> <plugin interceptor="com.hbst.basessm_3.dao.plugin.PageInterceptor"/> </plugins> </configuration>
4.2.5、创建spring配置文件applicationContext.xml 引入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:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.0.xsd"> <!-- 采用注释的方式配置bean --> <context:annotation-config /> <task:annotation-driven/> <context:component-scan base-package="com.hbst.basessm_3" /> <!-- proxy-target-class="true"强制使用CGLib代理,为false则spring会自动选择,否则事务不生效 --> <aop:aspectj-autoproxy proxy-target-class="true" /> <import resource="classpath:config/spring/spring-mybatis.xml" /> <!-- 模板引擎 --> <bean id="velocityEngine" class="org.springframework.ui.velocity.VelocityEngineFactoryBean" /> <!-- 异步线程 --> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <property name="corePoolSize" value="10" /> <property name="maxPoolSize" value="30" /> </bean> </beans>
5、至此,spring和mybatis整合完成,下面整合springMVC 我这里创建spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> <mvc:annotation-driven /> <context:component-scan base-package="com.hbst.basessm_3" /> <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="contentType" value="text/html" /> <property name="prefix" value="/" /> <property name="suffix" value=".jsp" /> </bean> <!-- rest json related... 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 class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="mappingJacksonHttpMessageConverter"/> </list> </property> </bean> <!-- rest json related... end --> </beans>
6、配置日志管理,创建log4j.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE log4j:configuration SYSTEM "../dtd/log4j.dtd"> <!-- ========================== 自定义输出格式说明================================ --> <!-- %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL --> <!-- %r 输出自应用启动到输出该log信息耗费的毫秒数 --> <!-- %c 输出所属的类目,通常就是所在类的全名 --> <!-- %t 输出产生该日志事件的线程名 --> <!-- %n 输出一个回车换行符,Windows平台为“/r/n”,Unix平台为“/n” --> <!-- %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921 --> <!-- %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10) --> <!-- ========================================================================== --> <!-- ========================== 输出方式说明================================ --> <!-- Log4j提供的appender有以下几种: --> <!-- org.apache.log4j.ConsoleAppender(控制台), --> <!-- org.apache.log4j.FileAppender(文件), --> <!-- org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件), --> <!-- org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件), --> <!-- org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方) --> <!-- ========================================================================== --> <!--Threshold是个全局的过滤器,他将把低于所设置的level的信息过滤不显示出来 --> <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true" threshold="debug"> <!-- 控制台打印日志 --> <appender name="console" class="org.apache.log4j.ConsoleAppender"> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} | %t | %-5p | %c%m%n" /> </layout> </appender> <!-- 输出到日志文件 --> <appender name="filelog_appender" class="org.apache.log4j.RollingFileAppender"> <!-- 设置File参数:日志输出文件名 --> <param name="File" value="${BaseSsm_1.root}/log/BaseSsm_3_debug.log" /> <!-- 设置是否在重新启动服务时,在原有日志的基础添加新日志 --> <param name="Append" value="false" /> <!-- 设置文件大小 --> <param name="MaxFileSize" value="10MB" /> <!-- 设置文件备份 --> <param name="MaxBackupIndex" value="300" /> <!-- 设置输出文件项目和格式 --> <layout class="org.apache.log4j.PatternLayout"> <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss} | %t | %-5p | %c %m%n" /> </layout> </appender> <category name="org.apache.log4j"> <priority value="warn" /> </category> <logger name="org.springframework"> <!-- <level value="info" /> --> <level value="debug" /> </logger> <logger name="com.opensymphony.xwork2"> <!-- <level value="info" /> --> <level value="debug" /> </logger> <!-- org.apache.axis2 | org.apache.struts2 --> <logger name="org.apache.axis2"> <level value="info" /> </logger> <logger name="org.apache.axiom"> <level value="warn" /> </logger> <logger name="org.apache.struts2"> <!-- <level value="info" /> --> <level value="debug" /> </logger> <logger name="org.apache.struts2.json"> <level value="debug" /> </logger> <logger name="org.apache.ibatis"> <level value="debug" /> </logger> <logger name="org.mybatis"> <level value="debug" /> </logger> <logger name="java.sql"> <level value="debug" /> </logger> <root> <priority value="debug" /> <appender-ref ref="console" /> <appender-ref ref="filelog_appender" /> </root> </log4j:configuration>
7、配置web.xml 在web.xm中引入spring配置文件、springMVC的配置文件和log4j.xml文件
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name>Archetype Created Web Application</display-name> <!-- RequestContextListener --> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <!-- 指定Web根目录 --> <context-param> <param-name>webAppRootKey</param-name> <param-value>BaseSsm_1.root</param-value> </context-param> <!-- FMT i18n Begin --> <context-param> <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> <param-value>i18n/lang_messages</param-value> </context-param> <filter> <filter-name>SetCharacterEncoding</filter-name> <filter-class>com.hbst.basessm_1.util.filter.SetCharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>SetCharacterEncoding</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- FMT i18n End --> <!-- 字符集过滤器 --> <filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <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>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 日志管理配置 --> <listener> <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> </listener> <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:log4j.xml</param-value> </context-param> <!-- 60s 检测日志配置 文件变化 --> <context-param> <param-name>log4jRefreshInterval</param-name> <param-value>60000</param-value> </context-param> <!-- Spring管理配置 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- 加载Spring配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:config/spring/applicationContext.xml </param-value> </context-param> <!-- Spring MVC配置 --> <servlet> <servlet-name>Dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- 自定义spring mvc的配置文件名称和路径 --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:config/spring/spring-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- spring mvc 请求后缀 --> <servlet-mapping> <servlet-name>Dispatcher</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app>
8、最后的目录结构是这样的,源代码已经提交github,有需要的可以下载源码看看,我这里提交的项目是basessm_1,跟basessm_3的结构是一样的,只需要修改下配置文件即可。
github地址是 https://github.com/1428977695/BaseSsm_3/tree/master/BaseSsm_1
9、测试,我这里使用basessm_1来测试
9.1、将项目部署到tomcat上,打开浏览器http://localhost:8080/BaseSsm_1
9.2、出现helloword,说明项目已经启动成功了,下面我们进行数据交互测试,
首先创建数据库,我这里创建user表 就两个字段 将这两个字段的值 显示在页面上
9.3、创建实体
9.4、创建mapper文件
9.5、配置实体别名映射
9.6、创建接口
9.7、创建实现类
9.8、这里将几个基础的类如baseDao.java PageInterceptor.java文件也放上来
9.8.1、接口IBaseDao
package com.hbst.basessm_1.dao; import java.util.List; import java.util.Map; public interface IBaseDao { /** * @Author:Dean * @Description:保存 * @param statement * SQLID * @param parameter * 参数 * @return boolean true 成功,false 失败 * @Date 2015年12月31日 */ public boolean insert(String statement, Object parameter); /** * @Author:Dean * @Description:更新 * @param statement * SQLID * @param parameter * 参数 * @return boolean true 成功,false 失败 * @Date 2015年12月31日 */ public boolean update(String statement, Object parameter); /** * @Author:Dean * @Description:删除 * @param statement * SQLID * @param parameter * 参数 * @return boolean true 成功,false 失败 * @Date 2015年12月31日 */ public boolean delete(String statement, Object parameter); /** * @Author:Dean * @Description:查询单条数据 * @param statement * SQLID * @param parameter * 参数 * @return Object * @Date 2015年12月31日 */ public Object findOneByCustom(String statement, Object parameter); /** * @param <T> * @Author:Dean * @Description: 查询集合列表 * @param statement * SQLID * @param parameter * 参数 * @return List<Object> * @Date 2015年12月31日 */ public <T> List<T> findListByCustom(String statement, Object parameter); /** * @param <T> * @Author:Dean * @Description: 分页查询 * @param statement * SQLID * @param parameter * 参数 * @return List<Object> * @Date 2015年12月31日 */ public Map<String,Object> findPageByCustom(String statement, Object parameter); }
9.8.2、实现类basedao
package com.hbst.basessm_1.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.beanutils.PropertyUtils; import org.apache.ibatis.executor.ErrorContext; import org.apache.ibatis.executor.ExecutorException; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.ParameterMapping; import org.apache.ibatis.mapping.ParameterMode; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.property.PropertyTokenizer; import org.apache.ibatis.scripting.xmltags.ForEachSqlNode; import org.apache.ibatis.session.Configuration; import org.apache.ibatis.type.TypeHandler; import org.apache.ibatis.type.TypeHandlerRegistry; import org.mybatis.spring.SqlSessionTemplate; import org.mybatis.spring.SqlSessionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Repository; import com.hbst.basessm_1.dao.IBaseDao; import com.hbst.basessm_1.util.constant.CodeConstant; import com.hbst.basessm_1.util.exception.BusinessException; import net.sf.json.JSONObject; @Repository("baseDao") public class BaseDao implements IBaseDao { @Autowired private SqlSessionTemplate sqlSessionTemplate; private long ROW_NUMBER = 0; private long ZERO = 0; public boolean insert(String statement, Object parameter) { if (null == parameter || null == statement) { throw new IllegalArgumentException(" Parameter Is Null."); } ROW_NUMBER = sqlSessionTemplate.insert(statement, parameter); return ROW_NUMBER > ZERO ? true : false; } public boolean update(String statement, Object parameter) { if (null == parameter || null == statement) { throw new IllegalArgumentException(" Parameter Is Null."); } ROW_NUMBER = sqlSessionTemplate.update(statement, parameter); return ROW_NUMBER > ZERO ? true : false; } public boolean delete(String statement, Object parameter) { if (null == parameter || null == statement) { throw new IllegalArgumentException(" Parameter Is Null."); } ROW_NUMBER = sqlSessionTemplate.delete(statement, parameter); return ROW_NUMBER > ZERO ? true : false; } public Object findOneByCustom(String statement, Object parameter) { if (null == parameter || null == statement) { throw new IllegalArgumentException(" Parameter Is Null."); } return sqlSessionTemplate.selectOne(statement, parameter); } public <T> List<T> findListByCustom(String statement, Object parameter) { if (null == parameter || null == statement) { throw new IllegalArgumentException(" Parameter Is Null."); } return sqlSessionTemplate.selectList(statement, parameter); } @SuppressWarnings("unchecked") public Map<String,Object> findPageByCustom(String statement, Object parameter) { if (null == parameter || null == statement) { throw new IllegalArgumentException(" Parameter Is Null."); } HashMap<String,Object> retMap = new HashMap<String,Object>(); //是否为分页查询 JSONObject jsonObject = JSONObject.fromObject(parameter); if (!(jsonObject.containsKey("pageNO") && null != jsonObject.get("pageNO") && jsonObject.containsKey("records") && null != jsonObject.get("records"))) { throw new BusinessException(CodeConstant.PARAMS_ERROR); } Integer pageNO = (Integer) jsonObject.get("pageNO") ; Integer records = (Integer) jsonObject.get("records"); if(pageNO!=null && pageNO>0 && records!=null && records>0){ retMap.put("recordsTotal", this.getTotalCount(statement, parameter)); retMap.put("data",sqlSessionTemplate.selectList(statement, parameter)); return retMap; } retMap.put("data",sqlSessionTemplate.selectList(statement, parameter)); return retMap; } /** * get total count * * @param sqlSession * @param statementName * @param values * @return */ private Integer getTotalCount(String statementName, Object values) { Map parameterMap = toParameterMap(values); Integer count = 0; try { MappedStatement mst = sqlSessionTemplate.getSqlSessionFactory() .getConfiguration().getMappedStatement(statementName); BoundSql boundSql = mst.getBoundSql(parameterMap); String sql = " select count(*) total_count from (" + boundSql.getSql() + ") as total"; Connection con = SqlSessionUtils .getSqlSession(sqlSessionTemplate.getSqlSessionFactory(), sqlSessionTemplate.getExecutorType(),sqlSessionTemplate.getPersistenceExceptionTranslator()) .getConnection(); PreparedStatement pstmt = con.prepareStatement(sql); // BoundSql countBS = new // BoundSql(mst.getConfiguration(),sql,boundSql.getParameterMappings(),parameterMap); setParameters(pstmt, mst, boundSql, parameterMap); ResultSet rs = pstmt.executeQuery(); if (rs.next()) { count = rs.getInt("total_count"); } rs.close(); con.close(); pstmt.close(); } catch (Exception e) { count = 0; e.printStackTrace(); throw new RuntimeException(e); } return count; } /** * 对SQL参数(?)设值,参考org.apache.ibatis.executor.parameter. * DefaultParameterHandler * * @param ps * @param mappedStatement * @param boundSql * @param parameterObject * @throws SQLException */ private void setParameters(PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql, Object parameterObject) throws SQLException { ErrorContext.instance().activity("setting parameters") .object(mappedStatement.getParameterMap().getId()); List<ParameterMapping> parameterMappings = boundSql .getParameterMappings(); if (parameterMappings != null) { Configuration configuration = mappedStatement.getConfiguration(); TypeHandlerRegistry typeHandlerRegistry = configuration .getTypeHandlerRegistry(); MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject); for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); PropertyTokenizer prop = new PropertyTokenizer(propertyName); if (parameterObject == null) { value = null; } else if (typeHandlerRegistry .hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else if (boundSql.hasAdditionalParameter(propertyName)) { value = boundSql.getAdditionalParameter(propertyName); } else if (propertyName .startsWith(ForEachSqlNode.ITEM_PREFIX) && boundSql.hasAdditionalParameter(prop.getName())) { value = boundSql.getAdditionalParameter(prop.getName()); if (value != null) { value = configuration.newMetaObject(value) .getValue( propertyName.substring(prop .getName().length())); } } else { value = metaObject == null ? null : metaObject .getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); if (typeHandler == null) { throw new ExecutorException( "There was no TypeHandler found for parameter " + propertyName + " of statement " + mappedStatement.getId()); } typeHandler.setParameter(ps, i + 1, value, parameterMapping.getJdbcType()); } } } } protected Map toParameterMap(Object parameter) { if (parameter == null) { return new HashMap(); } if (parameter instanceof Map) { return (Map<?, ?>) parameter; } else { try { return PropertyUtils.describe(parameter); } catch (Exception e) { e.printStackTrace(); return null; } } } }
9.8.3、分页拦截器
package com.hbst.basessm_1.dao.plugin;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;
import org.apache.ibatis.executor.resultset.ResultSetHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import net.sf.json.JSONObject;
/**
* @author tangguilin
* 分页拦截器
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class}),
@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class PageInterceptor implements Interceptor {
public Object intercept(Invocation invocation) throws Throwable {
if (invocation.getTarget() instanceof StatementHandler) {
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
//获取参数对象
DefaultParameterHandler parameterHander=(DefaultParameterHandler) metaStatementHandler.getValue("delegate.parameterHandler");
Object parameterObject = parameterHander.getParameterObject();
JSONObject jsonParameter = JSONObject.fromObject(parameterObject);
//是否分页
if(jsonParameter!=null && jsonParameter.has("pageNO")){
Integer pageNO = jsonParameter.getInt("pageNO");
Integer records = jsonParameter.getInt("records");
BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
String sql = boundSql.getSql();
StringBuffer sb=new StringBuffer();
sb.append(sql);
sb.append(" limit ").append((pageNO-1)*records).append(" , ").append(records);
metaStatementHandler.setValue("delegate.boundSql.sql", sb.toString());
}
}
return invocation.proceed();
}
/**
* 拦截类型StatementHandler
*/
public Object plugin(Object target) {
if (target instanceof StatementHandler) {
return Plugin.wrap(target, this);
} else {
return target;
}
}
public void setProperties(Properties properties) {
}
}
9.8.4、返回码文件
package com.hbst.basessm_1.util.constant;
/**
* 返回码
*
* @author lanshiyan description: code码为6位 每两位为一个级别分别代表不同的意思 前两位:级别 00 系统级别 01
*/
public interface CodeConstant {
/****************************************************************************/
/************************ BEGIN 00系统级别公共错误码 *************************/
/****************************************************************************/
/**
* 成功
*/
public static final String SUCCESS = "000000";
/**
* 参数验证错误码
*/
public static final String PARAMS_ERROR = "000001";
public static final String PARAMS_ERROR_DESCRIPTION = "Invalid method required parameter";
/**
* 系统异常错误码
*/
public static final String SYSTEM_ERROR = "000002";
public static final String SYSTEM_ERROR_DESCRIPTION = "Unknow system exception";
/****************************************************************************/
/************************ BEGIN 01业务级别登录错误码 **************************/
/****************************************************************************/
// ===========================================================================
// BEGIN 00公共错误码
// ===========================================================================
/**
* 用户名密码错误
*/
public static final String USERNAME_PWD_ERROR = "010001";
/**
* 参数为空
*/
public static final String PARARM_IS_EMPTY = "010002";
/**
* 不存在此用户
*/
public static final String SYSTEM_USER_NOT_EXISTS = "010003";
public static final String SYSTEM_USER_NOT_EXISTS_DESCRIPTION = "User not exists or bad user ID";
/**
* 密码复杂度不符合要求
*/
public static final String SYSTEM_BAD_PASSWORD_COMPLEXITY = "010004";
public static final String SYSTEM_BAD_PASSWORD_COMPLEXITY_DESCRIPTION = "Invalid password of complexity";
/**
* 旧密码错误
*/
public static final String SYSTEM_BAD_OLD_PASSWORD = "010005";
public static final String SYSTEM_BAD_OLD_PASSWORD_DESCRIPTION = "Invalid old password";
}
9.8.5、返回实体文件
package com.hbst.basessm_1.util.entity;
import java.io.Serializable;
/**
* 返回消息实体对象定义
*
* @author Dean 20160912
*/
public class ResultMessage implements Serializable {
private static final long serialVersionUID = 1L;
// 成功或失败的错误码,成功时返回000000
private String code;
// 失败时返回的错误消息
private String codeDesc;
// 当需要返回值时返回值对象,如果是查询列表,则返回queryList对象
private Object data;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCodeDesc() {
return codeDesc;
}
public void setCodeDesc(String codeDesc) {
this.codeDesc = codeDesc;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
return "ResultMessage [code=" + code + ", codeDes=" + codeDesc + ", data=" + data + "]";
}
}
9.8.6、系统自定义异常类
package com.hbst.basessm_1.util.exception;
import com.hbst.basessm_1.util.baseUtil.ResourceUtils;
import com.hbst.basessm_1.util.constant.CodeConstant;
/**
* 系统自定义异常类。
*
*
*
*/
public class BusinessException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 错误码。
*/
private String errorCode;
/**
* 问题
*/
private String errorDes;
/**
* 指定错误码与错误描述的异常。
*
* @param errorCode
* 错误码
* @param msg
* 异常信息
*/
public BusinessException(String errorCode, String msg) {
super(msg);
this.errorCode = errorCode;
this.errorDes = msg;
}
/**
* 指定错误码与错误描述的异常。
*
* @param errorCode
* 错误码
* @param msg
* 异常信息
*/
public BusinessException(String errorCode) {
super(ResourceUtils.getResultCodeDesc(errorCode));
this.errorCode = errorCode;
this.errorDes = (ResourceUtils.getResultCodeDesc(errorCode));
}
/**
* 未定义异常。
*/
public BusinessException() {
super(ResourceUtils.getResultCodeDesc(CodeConstant.SYSTEM_ERROR));
this.errorCode = CodeConstant.SYSTEM_ERROR;
}
public String getErrorDes() {
return errorDes;
}
public void setErrorDes(String errorDes) {
this.errorDes = errorDes;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
}
9.9、现在创建controller
9.10、在index.jsp中加入jquery.js,用jq的ajax方法去请求后台
9.11、刷新页面,点击按钮,会出现数据库里面插入的值。
10、到这里 ssm基础框架的整合,已经前后台交互就算完成。