1. ˼·
spring 和 mybatis 都是属于 web 框架,主要是为了处理用户的请求,访问数据库,将结果返回给页面进行渲染。因此,我整合的思路是从客户端发送的一个请求开始,根据 spring 处理请求的过程,逐步进行配置,完成 spring 和 mybatis 的整合,这样做的目的是为了熟悉每个配置的作用,那现在开始吧。
ע 本案例是基于 IDEA 创建的 Maven 项目
有关 spring mvc 的配置时依据这张图片完成的: 
该例子的文件结构如下:
首先,在 jsp 文件夹下创建 user.jsp 文件。该页面是向服务器发送一个 post 请求,参数是一个名为 id 的值。
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>UserTest</title> <%@ page isELIgnored="false"%> </head> <body> <form action="${pageContext.request.contextPath }/findUser" method="post"> id:<input type="text" name="id"> <input type="submit" value="查询"/> </form> </body> </html> 另外在相同文件夹下新建一个 result.jsp,为了下面进行测试
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>index</title> <%@ page isELIgnored="false"%> </head> <body> <h2>Find User</h2> <h2>${user.name}</h2> </body> </html> 当 spring 收到一个请求时,需要由 DispatcherServlet 来决定要交给哪个 HandlerMapping 处理。因此,我们得在 web.xml 中对 DispatcherServlet 进行配置。
DispatcherServler 会寻找 Hanldermapping,因此 Handlermapping 需要在也需要进行配置,如果不指定文件名的话,Handlermapping 的配置默认位置和默认文件名为 resource 文件夹下的 servletName-servlet.xml,如果我们需要修改默认的文件名和位置,可以在 标签下添加 标签进行配置。
<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:springmvc.xml</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> 根据上面的解释,我们需要为 HandlerMapping 添加配置,在 resources 文件夹下新建一个 springmvc.xml 对 HandlerMapping 进行配置。
而 HanlderMapper 需要根据 Controller 来确定跳转的页面,因此需要添加一个包扫描器,扫描 Controller 的位置。
页面具体跳转的位置是由 视图解析器 完成的,也是在这里对其进行配置。
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="controller"/> <!-- 注解的适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!-- 注解的适配器 --> <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans> 根据上面的包扫描器配置,我们在 java 文件夹下新建一个 controller 包,创建一个 UserController 来处理 user.jsp 的请求。当客户端在 user.jsp 输入 id 提交之后,会跳转到该页面。
package controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class UserController { @RequestMapping(value = "/findUser",method = RequestMethod.POST) public String findUser(){ return "result"; } @RequestMapping(value = "/index") public String ser(){ return "user"; } } 进行上面的配置之后,我们可以运行在浏览器地址栏访问下 http://localhost:8080/ssm/index 看是否能够跳转到 user.jsp,在 user.jsp 输入 id 之后,如果能够跳转到 result.jsp,则说明关于 spring mvc 的配置完成了。
为了使 UserController 能够访问数据库,我们添加对其进行修改:
@Controller public class UserController { @Autowired private UserService userService; @RequestMapping(value = "/findUser",method = RequestMethod.POST) public String findUser(int id,Model model){ User user = userService.findUser(id); model.addAttribute("user",user); return "result"; } @RequestMapping(value = "/index") public String ser(){ return "user"; } } 将访问数据库的任务交给 UserService 类,我们先创建 UserService 接口,它有一个 findUser 方法。
public interface UserService { public User findUser(int id); } 接着定义一个它的实现类
public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public User findUser(int id) { User user = userMapper.findUserById(id); return user; } } 其中 User 类的属性的定义和数据库中字段的定义一样
import java.util.Date; public class User { private int id; private String username; private Date birthday; private String sex; private String address; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } UserMapper 接口的任务是访问数据库,它的定义如下
import po.User; public interface UserMapper { public User findUserById(int id); } 按照 mybatis 的定义,应该创建一个和文件名为类名的配置文件 UserMapper.xml 放在相同的包下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="mapper.UserMapper"> <select id="findUserById" resultType="po.User" parameterType="int"> select * from user where id = #{id} </select> </mapper> 上面这些类调用的逻辑很简单,Controller 层调用 Service 层,而 Service 层使用 Mapper 层调用数据库,Mapper 层将查找结果转载到 po 层,即 User 类上。接下来的配置流程我们从 Mapper 层开始进行配置,然后是 Service、Controller。
为了使 Mapper 层能够访问到数据库,我们首先在 resource 文件夹下新建一个 applicationContext-dao.xml 用于进行数据库等相关配置。同时为了解耦,我们将数据库的信息独立出来,放在 resource 下的 db.properties
dataSource=org.apache.commons.dbcp.BasicDataSource jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/test jdbc.username=root jdbc.password= 在 applicationContext-dao.xml 中,我们首先应该找到 db.properties
<context:property-placeholder location="classpath:db.properties"/> 接着,设置数据源 DataSource
<bean id="dataSource" class="${dataSource}" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="5" /> </bean> 最后,进行 SqlSessionFactory 的配置。这里为了方便,在 mybatis-configuration.xml 就不进行配置。
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 加载mybatis的全局配置文件,放在classpath下的mybatis文件夹中 --> <!-- <property name="configLocation" value="classpath:mybatis-configuration.xml" /> --> <!-- 加载数据源,使用上面配置好的数据源 --> <property name="dataSource" ref="dataSource" /> </bean> 这是,Mapper 就可以访问数据库了,但是我们创建的是一个接口,mybais 提供了一个类,可以自动将接口转换成实现类,这个可以通过下面的配置来完成。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="mapper"></property> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> 至此,Service 可以调用 Mapper 的类了,但是 Controller 仍然不可以调用 Service 层的类,因为我们没有在 spring 容器中进行配置,所以,在 source 文件夹下新建一个 applicationContext-service.xml,将 UserService 注册到 spring ioc 容器中。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="service.UserServiceImpl"></bean> </beans> 到这里基本完成了 spring 和 mybatis 的整合,spring 容器如何寻找刚刚创建的 applicationContext-dao.xml 和 applicationContext-service.xml 呢?我们需要在 web.xml 中进行如下配置:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext-*.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> 至此,spring 和 mybatis 整合完成了,在 user.jsp 中输入 id,controller 访问数据库之后,将 user 存在 Model 类中,返回给 result.jsp,在 result.jsp 中将 user.username 显示出来。