Spring + Spring MVC + Mybatis 框架整合
最近学习Mybatis,学习了最基本的配置CRUD后,现在开始整合至Spring MVC.
一,框架说明
1, 系统使用maven构建Web项目
2,DB: MS sqlserver 2012
3,Server : Tomcat 8
4,Test : Junit
5,日志:slf4j + lobback
目录构建如下:
二,创建数据表
CREATE TABLE [dbo].[user_data]( [id] [int] IDENTITY(1,1) NOT NULL, [name] [nvarchar](50) NULL, [password] [nvarchar](150) NULL, [age] [int] NULL, CONSTRAINT [PK_user_data] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] GO INSERT INTO user_data VALUES('test_A','123456781',21); INSERT INTO user_data VALUES('test_B','123456782',22); INSERT INTO user_data VALUES('test_C','123456783',23); INSERT INTO user_data VALUES('test_D','123456784',24); INSERT INTO user_data VALUES('test_E','123456785',25);
三,添加依赖包: pom.xml 配置
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>luken</groupId> <artifactId>SSM</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <properties> <!-- spring version --> <spring.version>4.3.6.RELEASE</spring.version> <!-- aspectj version --> <aspectj.version>1.8.9</aspectj.version> <!-- logback version --> <logback.version>1.2.1</logback.version> </properties> <dependencies> <!-- spring mvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <!-- spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</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-test</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <!-- aspectj --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>${aspectj.version}</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>${aspectj.version}</version> </dependency> <!-- db: sql server --> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>6.1.0.jre8</version> </dependency> <!-- mybatis orm --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency> <!-- DBCP2 连接池 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-dbcp2</artifactId> <version>2.1.1</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency> <dependency> <groupId>org.apache.geronimo.specs</groupId> <artifactId>geronimo-jta_1.1_spec</artifactId> <version>1.1.1</version> </dependency> <!-- c3p0 连接池 --> <dependency> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> <version>0.9.1.2</version> </dependency> <!-- jackson : json support --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.5</version> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.7</version> </dependency> <!-- file upload --> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.2</version> </dependency> <!-- properties file yaml support --> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>1.17</version> </dependency> <!-- servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> </dependency> <!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- slf4j --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <!-- logback : slf4j + logback --> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>${logback.version}</version> </dependency> <!-- junit test --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> </dependencies> <!-- 添加指定jdk版本插件 --> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
四,配置实体 User.java
package com.luken.model; public class User { private int id; private String name; private String password; private int age; @Override public String toString() { return "User [id=" + id + ", name=" + name + ", password=" + password + ", age=" + age + "]"; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
五,配置Mybatis ORM 映射接口
package com.luken.dao; import java.util.List; import org.apache.ibatis.annotations.Param; import com.luken.model.User; public interface UserDao { public User findUserById(@Param("id") int id); public List<User> findUserList(); public int addUser(User user); public int updateUser(User user); public int delUser(@Param("id") int id); }
六,创建的映射文件,在资源文件目录resources下,新建conf/mybatis/mapping/UserMapper.xml(命名尽量都遵循一个规则,便于扫描,这里是用 “实体名+Mapper”)如下:
<?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 namespace="com.luken.dao.UserDao"> <!-- 通过Id查找 --> <select id="findUserById" resultType="com.luken.model.User"> select * from user_data u where id=#{id} </select> <!-- 查询所有的User --> <select id="findUserList" resultType="com.luken.model.User"> SELECT u.id, u.name, u.password, u.age FROM user_data u; </select> <!-- 添加 --> <insert id="addUser" parameterType="com.luken.model.User"> insert into user_data values(#{name},#{password},#{age}) </insert> <!-- 删除 --> <delete id="delUser" > DELETE FROM user_data WHERE id=#{id} </delete> <!-- 更新 --> <update id="updateUser"> UPDATE user_data SET name=#{name},password=#{password},age=#{age} WHERE id=#{id} </update> </mapper>
七,Spring 整合Mybatis配置
7.1 在resources文件夹下,新建一个名为 ssm 文件夹,并在ssm文件夹上新建文件 config.yml , config.yml用于存放项目的配置信息
jdbc: driver: com.microsoft.sqlserver.jdbc.SQLServerDriver url: jdbc:sqlserver://10.180.139.246:1433;DatabaseName=mybatis username: yourname password: yourpwd
7.2 配置Mybatis与spring 整合
(1) 在resources根目录下,新建文件夹 conf/spring,然后在spring文件夹下建spring-datasource.xml
(2) datasource 连接池选择dbcp2,刚开始选择c3p0,查询时间匹配String字段报错,原因还没有花时间找,待找到后,再作说明修改。
Spring-datasource.xml 内容如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!-- 连接池 dbcp2 配置 --> <bean id="dataSource" class="org.apache.commons.dbcp2.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}" /> <!-- 连接池启动时创建的连接数量的初始值 默认值是0 --> <property name="initialSize" value="3" /> <!-- 最小空闲值 默认值是0 --> <property name="minIdle" value="3" /> <!-- 最大空闲值 0时无限制 默认值是8 --> <property name="maxIdle" value="5" /> <!-- 连接池的最大值 0时无限制 默认值是8 --> <property name="maxTotal" value="15" /> </bean> <!-- 配置sqlSessionFactory: spring和MyBatis完美整合,不需要mybatis的配置映射文件 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="configLocation" value="classpath:conf/mybatis/mybatis-config.xml" /> <!-- 自动扫描mapping.xml文件 --> <property name="mapperLocations" value="classpath:conf/mybatis/mapping/*.xml" /> </bean> <!-- DAO接口所在包名,Spring会自动查找其下的类 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.luken.dao" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> </beans>
7.3 配置Spring IOC, 在resources/conf/spring 目录下新建文件:spring-context.xml
spring-context.xml 配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd"> <!-- 自动扫描组件包 --> <context:component-scan base-package="com.luken.*" /> <aop:aspectj-autoproxy /> <!-- 加载配置文件 --> <bean id="yamlProperties" class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean"> <property name="resources" value="classpath:ssm/config.yml" /> </bean> <context:property-placeholder properties-ref="yamlProperties" /> <!-- (事务管理)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>
7.4
mybatis-config.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> <settings> <setting name="cacheEnabled" value="false"/> <setting name="mapUnderscoreToCamelCase" value="true"/> <setting name="useGeneratedKeys" value="true"/> <setting name="safeRowBoundsEnabled" value="false"/> <setting name="defaultExecutorType" value="REUSE"/> <setting name="defaultStatementTimeout" value="600"/> </settings> <typeAliases> <typeAlias alias="User" type="com.luken.model.User"/> </typeAliases> <!-- 如果选择了“自动扫描mapping.xml文件”,则不需要配置mappers --> <!-- <mappers> <mapper resource="conf/mybatis/mapping/userMapper.xml"/> </mappers> --> </configuration>
八,写服务层(service层)
8.1 UserService.java 接口类
package com.luken.service; import java.util.List; import org.apache.ibatis.annotations.Param; import com.luken.model.User; public interface UserService { public User findUserById(int id); public List<User> findUserList(); public int addUser(User user); public int updateUser(User user); public int delUser(@Param("id") int id); }
8.2 UserServiceImpl.java 实现类
package com.luken.service; import java.util.List; import javax.annotation.Resource; import org.springframework.stereotype.Service; import com.luken.dao.UserDao; import com.luken.model.User; @Service public class UserServiceImpl implements UserService { @Resource UserDao userDao; @Override public User findUserById(int id) { return this.userDao.findUserById(id); } @Override public List<User> findUserList() { return this.userDao.findUserList(); } @Override public int addUser(User user) { return this.userDao.addUser(user); } @Override public int updateUser(User user) { return this.userDao.updateUser(user); } @Override public int delUser(int id) { // TODO Auto-generated method stub return this.userDao.delUser(id); } }
九,配置日志 : slf4j + logbock
到目前为止,spring整合mybatis基本完成,先对其进行单元测试,测试前先配置日志(可以省略)
9.1 在resources文件夹下新建文件:logback.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <!-- encoder 默认配置为PatternLayoutEncoder --> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n </pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="STDOUT" /> </root> </configuration>
十, Junit测试
10.1 测试datasource配置
package com.luken.test; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import javax.sql.DataSource; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDataSource { private static ApplicationContext context; public static void main(String args[]) throws SQLException { context = new ClassPathXmlApplicationContext("conf/spring/spring-context.xml", "conf/spring/spring-datasource.xml"); DataSource ds = context.getBean("dataSource", DataSource.class); java.sql.Connection conn = ds.getConnection(); String sql = "select * From user_data"; PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery(); while (rs.next()) { System.out.println(rs.getString(1)); System.out.println(rs.getString(2)); System.out.println(rs.getString(3)); } if (ps != null) { ps.close(); } if (conn != null) { conn.close(); } } }
测试结果:
1 test_A 123456781 2 test_B 123456782 3 test_C 123456783 4 test_D 123456784 5 test_E 123456785
10.2 测试spring + mybatis整合
package com.luken.test; import org.junit.runner.RunWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.luken.model.User; import com.luken.service.UserService; @ContextConfiguration(locations = { "classpath:conf/spring/spring-context.xml", "classpath:conf/spring/spring-datasource.xml" }) @RunWith(SpringJUnit4ClassRunner.class) public class TestSM { private static Logger logger = LoggerFactory.getLogger(TestSM.class); @Autowired UserService userService; @org.junit.Test public void test() { User user = userService.findUserById(1); logger.info("用户:{}", user); } }
测试结果:
16:11:42.109 [main] INFO com.luken.test.TestSM - 用户:User [id=1, name=test_A, password=123456781, age=21]
十一,配置 spring MVC
11.1 在resources/conf/spring 文件夹中添加spring-mvc.xml文件
Spring-mvc.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:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!-- 扫描 --> <context:component-scan base-package="com.luken.web.controller" /> <!-- 驱动注解 --> <mvc:annotation-driven /> <!-- 配置默认mvc servlet --> <mvc:default-servlet-handler /> <!-- 配置 viewResolver --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> </beans>
11.2 配置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" id="WebApp_ID" version="3.0"> <display-name>SSM</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <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:conf/spring/spring-mvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- spring 容器启动配置 --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:conf/spring/spring-context.xml, classpath:conf/spring/spring-datasource.xml</param-value> </context-param> <!-- Encoding Filter --> <filter> <filter-name>encodingFilter</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> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- spring beans的防止内存泄露 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!-- error page --> <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/notfound.jsp</location> </error-page> </web-app>
11.3 在webapp 目录下分别新建index.jsp,error.jsp, notfound.jsp,并在/WEB-INF/ 目录下新建 views 文件夹
(此项目中也可以不建,与 Spring-mvc.xml viewResolver preffix 一致)
十二,mvc controller
12.1 UserController.java
其实还有删除和修改的方法没有写,可留给大家自行测试
package com.luken.web.controller; import java.util.Date; import java.util.List; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.luken.model.User; import com.luken.service.UserService; @RestController @RequestMapping("user") public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Resource private UserService userService; @RequestMapping("/findUserById") public User findUserById(HttpSession session,@RequestParam int id ){ User user = this.userService.findUserById(id); return user; } @RequestMapping(path = {"findUserList"}, method = {RequestMethod.GET}) public List<User> findUserList() { return this.userService.findUserList(); } @RequestMapping(path = {"addUser"}, method = {RequestMethod.GET}) public String addUser(HttpSession session, @RequestParam String name, @RequestParam String password, @RequestParam int age) { User user = new User(); user.setName(name); user.setPassword(password); user.setAge(age); int retResult = this.userService.addUser(user); String result = " add success"; if(retResult == 0) { result = "fail"; } return result; } }
十三,运行ssm项目
测试 输入url: http://localhost:8081/SSM/user/findUserList
得到的结果为:
[{"id":1,"name":"test_A","password":"123456781","age":21},{"id":2,"name":"test_B","password":"123456782","age":22},{"id":3,"name":"test_C","password":"123456783","age":23},{"id":4,"name":"test_D","password":"123456784","age":24},{"id":5,"name":"test_E","password":"123456785","age":25}]
测试 输入url: http://localhost:8081/SSM/user/findUserById?id=2
得到的结果为:
{"id":2,"name":"test_B","password":"123456782","age":22}
总结
至此,spring + spring mvc + mybatis 整合配置完成,由于是第一次配置,其中也遇到一些问题
1,mapper 命名空间要是接口的 包名+接口名 一至
2,采用扫描的方式 扫描 mapper xml 其可以省略导入mybatis-config.xml
3, 连接池的选择,也可选用c3p0 连接池
<!-- 连接池 c3p0 配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="${jdbc.driver}" /> <property name="jdbcUrl" value="${jdbc.url}" /> <property name="user" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
由于水平有限,有问题可以提出,共同进步