在前面的几篇博客中给大家介绍了Spring框架,并且简单的分析了一下IOC和AOP的实现原理以及手动的实现了一个简单的demo。由于小风这段时间一直在写C语言的项目,所以博文连续断更几个月了。刚好最近不忙,准备继续开始分享一些常用的技术了。
今天主要给大家介绍Spring框架整合其他技术的解决方案。现如今使用的最多的组合框架就是Spring+MyBatis了。前段时间给大家介绍的都是原理性的东西,今天就给大家讲解一个实战案例,使用我们熟悉的Spring框架整合MyBatis实现一个查询的案例。
首先我们先准备好SSM框架整合的一些jar包,其中Mybatis下载之后的结构如下图所示:
我们可以从官网上下载到两个压缩包,这里我们解压这两个压缩包,发现其中带有source的压缩包里面是MyBatis的源码,因此我们需要的应该是在第一个文件夹里。打开第一的文件夹,如下图所示:
打开之后我们可以看到如下的结构,其中lib目录下的是MyBatis依赖的相关技术,但是我们使用的时候仅需要mybatis-3.4.1.jar这个文件。pdf文件毫无疑问就是MyBatis框架的文档了,关于MyBatis的教程下个月会给大家准备案例介绍。
打开eclipse,创建一个动态web工程,并且创建出如下的包结构,如下图所示:
接着,我们需要在lib目录下导入本次需要使用的相关jar包。除了Spring和MyBatis的jar包之外我们还需要数据库驱动、数据库连接池(c3p0)的jar包,除此之外还需要标签库的包。具体如下图所示:
关于上图中Spring的这些jar包都是做什么的可以参考https://blog.csdn.net/qq_38701478/article/details/82929353这篇博文的介绍。对了,还有一个重要的jar包是mybatis-spring的这个包,这个包的作用就是将spring和MyBatis框架联系在一起的包,他的作用就像是一瓶胶水,将MyBatis框架和Spring粘在一起。对了,MyBatis的jar包可以去官网下载(http://www.mybatis.org/mybatis-3/zh/getting-started.html),值得庆幸的是MyBatis官方文档有中文版的,打开前面的网址,如下图所示:
进入到这个页面之后我们就可以看到了MyBatis的简介了,这里我们选择左侧的入门,进入如下图所示的界面:
我们点击红色框框的部分,就会跳转的一个(全球最大的同性交友)神奇的网站,关于这个网站以后会给大家介绍,毕竟这个是程序员必备的一个网站之一,好了,进入到GitHub页面之后,我们找到下图所示的地方就可以下载mybatis的jar包了。
好了,简单的介绍了一下MyBatis框架的下载方法,回到我们今天的话题上,创建好了工程,导入了相关的jar包之后我们就来开始正式的来整合这两个技术了。
首先,我们都知道Spring是一个容器,这个容器可以帮助我们去管理对象以及对象之间的依赖关系,那么我们就可以想一下,这个容器什么时候创建呢,毫无疑问,我们需要在应用程序被加载的时候就需要创建 Spring的容器,让Spring容器去创建对象和管理对象。因此,我们就需要在web.xml中配置一个监听器,当程序启动的时候,立即创建Spring容器。打开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_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- 初始化spring容器 -->
<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>
<!-- 前端控制器 -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
其中,上面的这段配置的意思就是,在应用程序被加载的时候就创建一个
org.springframework.web.context.ContextLoaderListener的实例,当然创建该类的实例的时候还需要一个配置文件,同样的我们还需要配置一个前端控制器,用来处理页面上用户接收的请求。同样的创建前端控制器也需要一个配置文件。配置好了web.xml文件之后我们就来创建这两个文件。
我们在conf目录下创建两个xml文件,分别命名为applicationContext.xml和spring-mvc.xml。首先我们来编写spring-mvc.xml文件,我们在其中加入如下的文件:
<!-- 组件扫描 -->
<context:component-scan base-package="com.wcan.ssm" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 视图解析器 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
上述的配置文件中主要配置了两个 部分,第一个是组件扫描,它的作用是扫描指定的包下面的类,并将他们管理到IOC容器中,这里需要注意的是我们在web层仅仅需要管理Controller组件即可,因此我们需要将默认的扫描规则设置成false。并且使用context:include-filter标签来指定扫描Controller组件即可。第二个是视图解析器,它的作用是根据用户的请求返回给用户一个视图,也就是一个页面。并且这个页面的前缀是/WEB-INF/views/,后缀是.jsp。这个稍后解释。
接下来我们再来配置applicationContext.xml,这个文件就是Spring的核心容器的配置文件了。该文件的内容如下所示:
<!-- 组件扫描 -->
<context:component-scan base-package="com.wcan.ssm">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<!-- 数据源 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 声明式事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 开启事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 整合MyBatis -->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
<!-- 全局配置文件 -->
<property name="configLocation" value="classpath:MyBatis.xml"></property>
<!-- 映射文件 -->
<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"></property>
<!-- 别名处理 -->
<property name="typeAliasesPackage" value="com.wcan.ssm.pojo"></property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.wcan.ssm.mapper"></property>
</bean>
既然是Spring整合MyBatis框架,那么我们的基本思路就是让Spring来管理MyBatis的SessionFactoryBean了。由于我们在程序中需要用到注解,因此依然需要配置一个组件扫描用来扫描程序中的注解,注意这里和Spring-mvc.xml中不通的是这里需要扫描的是除了Controller之外的注解,这并不难理解,因为我们的Controller类已经被SpringMVC管理了。
由于我们这次的案例需要连接数据库,因此接下来就是让Spring来管理我们的数据源了,为了程序的扩展性,我们将数据库的配置文件单独写在db.properties文件中,然后在applicationContext.xml文件中通过context:property-placeholder标签来加载配置文件,以后如果我们的数据库迁移了或者更改了密码我们只需要修改db.properties文件就可以了。
接着便是配置声明式事务了。配置好了事务管理器之后我们使用tx:annotation-driven标签即可开启声明式事务,关于声明式事务的原理可以参考小风前面的文章。
然后便是本篇博客的核心部分了,我们将MyBatis的SqlSessionFactoryBean的实例交给Spring来管理,同时将全局配置文件MyBatis.xml和mapper文件注入到Spring容器中。同时还需要配置一个别名,作用就是标识需要被代理的mapper接口对应的实体类。
最后我们还需要将MyBatis的MapperScannerConfigurer实例交给Spring来进行和管理,该实例的作用就是加载mapper接口。在程序运行的时候为该接口动态的创建实例。
接下来就是MyBatis的远距配置文件MyBatis.xml了,在实际开发中我们并不需要在该文件中配置一些和业务相关的内容,最常用的也就是一些射射规则和启用框架的缓存策略。该文件内容如下:
<!-- 配置 -->
<configuration>
<!-- 2. settings: 包含了很多重要的设置项 -->
<settings>
<!-- 映射下划线到驼峰命名 -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
<!-- 开启延迟加载 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 配置按需加载-->
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
</configuration>
然后就是数据库的配置文件db.properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/data-service?allowMultiQueries=true
jdbc.username=root
jdbc.password=root
这个文件就不解释了哈,把上面的url,username以及password改成自己的就可以了。emmmmmm..............准备工作做的差不多了。
好了,至此SSM的环境基本架构搭建完毕。来梳理一下Spring整合MyBatis框架的几个步骤:
1、在web.xml中配置Spring启动的监听器,当程序被加载的时候就可以创建出Spring的容器。
2、配置SpringMVC的前端控制器,用来拦截用户的请求,将用户的请求交给对应的Controller来处理。
3、编写SpringMVC 的配置文件,需要配置一个包扫描器(组件) 和视图解析器
4、编写Spring的配置文件,开启组件扫描(注意排除controller组件)、管理数据源,以及创建MyBatis的 SqlSessionFactoryBean。最后把MyBatis的MapperScannerConfigurer组件注入到容器中。
5、编写MyBatis的全局配置文件,一般可以将那些和业务无关的配置写在这个文件中。
接下来我们来准备数据,首先创建一张user表,表结构属下图所示:
接着在pojo包下创建一个User类,代码如下:
public class User {
Integer id;
String userName;
String department;
Integer depId;
String phoneNumber;
String carId;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public Integer getDepId() {
return depId;
}
public void setDepId(Integer depId) {
this.depId = depId;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getCarId() {
return carId;
}
public void setCarId(String carId) {
this.carId = carId;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", department=" + department + ", depId=" + depId
+ ", phoneNumber=" + phoneNumber + ", carId=" + carId + "]";
}
}
继续,我们来创建一个UserMapper接口,在该接口中我们定义一个方法,查询所有的用户信息。代码如下:
public interface UserMapper {
public List<User> selectAllUser();
}
然后继续在对应的路径(这里我用的是类路径下的mybatis/mapper/)下创建UserMapper.xml文件,并且我们在该文件中写入一条sql语句,内容如下:
<?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.wcan.ssm.mapper.UserMapper">
<select id= "selectAllUser" resultType="User">
select * from sys_user
</select>
</mapper>
然后就是service层的一个UserService接口和它的实现类UserServiceImpl。内容如下:
public interface UserService {
public List<User> selectAllUser();
}
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public List<User> selectAllUser() {
// TODO Auto-generated method stub
return userMapper.selectAllUser();
}
}
最后我们来编写Controller。在Controller中调用Service层的方法实现查询的功能。
@Controller
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/getUserMsg")
@ResponseBody
public Map<String,Object> getUserMsg(Map<String,Object> map){
List<User> list = userService.selectAllUser();
map.put("users", list);
return map;
}
}
好了,项目基本完成了。身下的我们再来一个页面,在/WEB-INF/views/路径下创建一个jsp文件。内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 align="center"> 用户信息 列表 </h1>
<br>
<table align="center" border="1px" width="95%" cellspacing="0px">
<tr>
<th>用户id</th>
<th>用户姓名</th>
<th>部门名</th>
<th>部门id</th>
<th>手机号码</th>
<th>身份证号码</th>
</tr>
<c:forEach items="${users }" var = "user">
<tr>
<td>${user.id }</td>
<td>${user.userName }</td>
<td>${user.department }</td>
<td>${user.depId }</td>
<td>${user.phoneNumber }</td>
<td>${user.carId}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
完美了,接下来我们启动tomcat,打开浏览器,访问http://localhost:8080/ssm_demo/getUserMsg
效果如下图所示:
好了,本次就给大家介绍这么多了,相信大家应该会有一些问题,尤其是配置文件中许多name和value的取值。关于这些问题我会在下一篇博客中及详细的给大家介绍。现在大家就赶紧试试这个激动人心的小项目吧。