JavaWeb学习中关于整合SSM的相关知识 💯💤
SSM整合
采用Spring整合MyBatis以及SpringMVC的方式,使用XML+注解的配置方式。
¶1. 准备工作
¶1. 创建数据库表
create database ssm;
use ssm;
create table account(
id int primary key auto_increment,
name varchar(20),
money double
);
¶2. 创建maven工程并导入依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<mysql.version>5.1.6</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</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-webmvc</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-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
<!-- el表达式 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- log start -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- log end -->
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- Spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
</dependencies>
¶3. 编写实体类
public class Account implements Serializable {
private Integer id;
private String name;
private Double money;
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Double getMoney() {
return money;
}
public void setMoney(Double money) {
this.money = money;
}
}
¶4. 持久层接口
因为使用了mybatis框架,dao中不需要提供实现类,会由mybatis生成代理对象去实现。
public interface AccountDao {
/**
* 查询所有账户
*
* @return
*/
public List<Account> findAll();
/**
* 保存账户信息
*
* @param account
*/
public void saveAccount(Account account);
}
¶5. 业务层接口及实现类
AccountService
public interface AccountService {
/**
* 查询所有账户
*
* @return
*/
public List<Account> findAll();
/**
* 保存账户信息
*
* @param account
*/
public void saveAccount(Account account);
}
AccountServiceImpl
public class AccountServiceImpl implements AccountService {
@Override
public List<Account> findAll() {
System.out.println("业务层:查询所有账户...");
return null;
}
@Override
public void saveAccount(Account account) {
System.out.println("业务层:保存账户信息...");
}
}
¶2. Spring配置
¶1.创建配置文件
在resources目录下创建Spring的配置文件applicationContext.xml
。
由于表现层采用了SpringMVC的框架去实现,所以不需要在Spring中配置web层注解,需要忽略这一部分。
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 开启注解扫描,要扫描的是service和dao层的注解,要忽略web层注解,因为web层让SpringMVC框架去管理 -->
<context:component-scan base-package="cn.sucrelt">
<!-- 配置要忽略的注解 -->
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
¶2. 业务层实现类加入Spring容器中
将AccountServiceImpl
通过注解加入到Spring容器中
@Service("accountService")
public class AccountServiceImpl implements AccountService {
...
}
¶3. 测试
public class TestSpring {
@Test
public void run1() {
//加载配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
//获取对象
AccountService accountService = (AccountService) ac.getBean("accountService");
//调用方法
accountService.findAll();
}
}
测试结果:控制台显示执行了业务层的方法。
¶3. 整合SpringMVC
¶1. 目的
- 首先搭建SpringMVC框架,包括配置
web.xml
、springmvc.xml
文件,编写AccountController
控制器类(也是web表现层)、以及响应的前端请求界面index.jsp
和最后跳转界面list.jsp
。 - 整合的目的是使用controller控制器类作为web层,即能够在controller中调用service方法。
¶2.分析
服务器启动之后,会加载配置文件web.xml
,其中加载前端控制器从而加载springmvc的配置文件,但是spring的配置文件没能加载,所以需要在web.xml
中使用配置监听器,用于加载spring的配置文件applicationContext.xml
。
¶3. 配置监听器
在项目启动的时候,就去加载applicationContext.xml的配置文件,在web.xml中配置ContextLoaderListener
监听器(该监听器只能加载WEB-INF目录下的applicationContext.xml的配置文件),所以需要设置加载类路径下的文件。
当加载了spring的配置文件后,就会启动spring注解的扫描,在之后控制器中使用注解自动注入service对象便会生效。
<!-- 配置监听器,用于加载spring的配置文件applicationContext.xml -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
¶4. 在控制器中调用service方法
在控制器中调用service方法,实现Spring和SpringMVC的整合,service方法进行自动注入。
@Controller
@RequestMapping("/account")
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping("/findAll")
public String findAll() {
System.out.println("表现层:查询所有账户信息...");
accountService.findAll();
return "list";
}
}
¶5. 测试
通过index.jsp请求
<body>
<a href="account/findAll">测试Spring+SpringMVC</a>
</body>
测试结果:请求到达web层,即SpringMVC框架中的前端控制器,执行表现层方法,其中调用了accountService.findAll()
,便进入Spring框架中的业务层,执行业务层方法。控制台输出为:
表现层:查询所有账户信息...
业务层:查询所有账户...
¶4. 配置MyBatis
个中细节参考MyBatis的文档。
¶1. 编写MyBatis配置文件
<?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>
<!-- 配置环境 -->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF-8&serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</dataSource>
</environment>
</environments>
<!-- 引入映射的配置文件,使用的是注解,引入对应dao类 -->
<mappers>
<!--该包下的所有dao接口都可用-->
<package name="cn.sucrelt.dao"/>
</mappers>
</configuration>
¶2. 注解配置dao类
public interface AccountDao {
@Select("select * from account")
public List<Account> findAll();
@Insert("insert into account (name, money) values (#{name}, #{money})")
public void saveAccount(Account account);
}
¶5. 整合MyBatis
¶1. 分析
service使用Spring框架实现,service的类存入到Spring的IOC容器中,由于MyBatis使用代理对象实现dao功能,整合的目的就是要让代理对象也加入到Spring容器中,从而被service对象调用。
¶2. 配置applicationContext.xml
把SqlMapConfig.xml配置文件中的内容配置到applicationContext.xml配置文件中,除了环境和映射的配置外,还要配置SqlSession的工厂,从而将代理对象加入到Spring容器中。
原有的SqlMapConfig.xml可以删除。
<!-- 整合Mybatis -->
<!-- 配置连接池对象 -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm?characterEncoding=UTF-8&serverTimezone=GMT"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
<!-- 配置SqlSession的工厂 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置扫描dao的包 -->
<bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="cn.sucrelt.dao"/>
</bean>
¶3. 修改service和dao
-
dao类上加上
@Repository
注解@Repository public interface AccountDao { @Select("select * from account") public List<Account> findAll(); @Insert("insert into account (name, money) values (#{name}, #{money})") public void saveAccount(Account account); }
-
service实现类中自动注入dao类并调用其中方法
@Service("accountService") public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; @Override public List<Account> findAll() { System.out.println("业务层:查询所有账户..."); return accountDao.findAll(); } @Override public void saveAccount(Account account) { System.out.println("业务层:保存账户信息..."); accountDao.saveAccount(account); } }
¶4.测试
修改控制器和前端代码进行测试
控制器:
@Controller
@RequestMapping("/account")
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping("/findAll")
public String findAll(Model model) {
System.out.println("表现层:查询所有账户信息...");
List<Account> list = accountService.findAll();
for (Account account : list) {
System.out.println(account);
}
model.addAttribute("list", list);
return "list";
}
}
index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="account/findAll">测试Spring+SpringMVC</a>
</body>
</html>
list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>显示查询的所有用户</h3>>
${list}
</body>
</html>
¶5. 添加事务管理
整合MyBatis的事务管理同样也配置在applicationContext.xml中。
<!--配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="find*" read-only="true"/>
<tx:method name="*" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!--配置AOP增强-->
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.sucrelt.service.impl.*ServiceImpl.*(..))"/>
</aop:config>
¶6. 整合流程分析
- 前端界面发送请求到控制器;
- 控制器使用SpringMVC框架,整合到Spring框架中后,可以调用Spring中的service类并自动注入。
- 执行service实现类中的方法,其中调用了dao类的方法并自动注入。
- dao类采用MyBatis的配置,配置项放在Spring的配置文件中,实现整合。