当前位置:网站首页>SSM整合
SSM整合
2022-07-17 05:24:00 【YMeng_Zhang】
目录
6. 编写 SpringMVC 在 SSM 环境中可以单独使用
前言
在分别了解spring,springmvc和mybatis后,这篇文章将以实现一个小的需求的形式,对其进行整合。
1. 需求和步骤分析
需求:使用 SSM 框架完成对 account 表的增删改查操作。
步骤分析:
- 准备数据库和表记录
- 创建 web 项目
- 编写 MyBatis 在 SSM 环境中可以单独使用
- 编写 Spring 在 SSM 环境中可以单独使用
- Spring 整合 MyBatis
- 编写 SpringMVC 在 SSM 环境中可以单独使用
- Spring 整合 SpringMVC
2. 环境搭建
2.1 准备数据库和表记录
CREATE TABLE `account` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) DEFAULT NULL,
`money` double DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
insert into `account`(`id`,`name`,`money`) values (1,'tom',1000),(2,'jerry',1000);
2.2 创建 web 项目
使用 Maven 创建名为 ssm 的 web 项目
3. 编写 MyBatis 在 SSM 环境中可以单独使用
需求:基于 MyBatis 先来实现对 account 表的查询
相关坐标
...
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.15</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
...
Account 实体
public class Account {
private Integer id;
private String name;
private Double money;
// getter and setter ...
}
AccountDao 接口
public interface AccountDao {
public List<Account> findAll();
}
AccountDao.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="com.zm.dao.AccountDao">
<select id="findAll" resultType="com.zm.domain.Account">
select * from account
</select>
</mapper>
MyBatis 核心配置文件
jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///spring_db?characterEncoding=utf8&useSSL=false
jdbc.username=root
jdbc.password=password
SqlMapConfig.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>
<!-- 加载 properties -->
<properties resource="jdbc.properties"/>
<!-- 类型别名配置 -->
<typeAliases>
<package name="com.zm.domain"/>
</typeAliases>
<!-- 环境配置 -->
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!-- 加载映射 -->
<mappers>
<package name="com.zm.dao"/>
</mappers>
</configuration>
测试代码
public class MyBatisTest {
@Test
public void testMybatis() throws IOException {
InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
SqlSession sqlSession = sqlSessionFactory.openSession();
AccountDao mapper = sqlSession.getMapper(AccountDao.class);
List<Account> all = mapper.findAll();
for (Account account : all) {
System.out.println(account);
}
sqlSession.close();
}
}
4. 编写 Spring 在 SSM 环境中可以单独使用
导入相关坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
AccountService 接口
public interface AccountService {
List<Account> findAll();
}
AccountServiceImpl 实现
@Service
public class AccountServiceImpl implements AccountService {
@Override
public List<Account> findAll() {
System.out.println("findAll 执行了...");
return null;
}
}
Spring 核心配置文件
applicationContext.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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:conext="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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置 IOC 相关操作: 开启注解扫描 -->
<conext:component-scan base-package="com.zm.service"/>
</beans>
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
@Autowired
private AccountService accountService;
@Test
public void testSpring() throws Exception {
List<Account> accountList = accountService.findAll();
System.out.println(accountList);
}
}
5. Spring 整合 MyBatis
整合思想
将 MyBatis 接口代理对象的创建权交给 Spring 管理,我们就可以把 Dao 的代理对象注入到 Service 中,此时也就完成了 Spring 与 MyBatis 的整合了。
导入整合包
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
Spring 配置文件管理 MyBatis
此时可以将 MyBatis 主配置文件 SqlMapConfig.xml 删除,在 applicationContext.xml 配置文件中加入 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:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:conext="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
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 配置 IOC 相关操作: 开启注解扫描 -->
<conext:component-scan base-package="com.zm.service"/>
<!-- spring 整合 mybatis 开始 -->
<!-- 引入 jdbc.properties -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 创建数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- sqlSessionFactory 的创建权交给了 spring,生产 sqlSession -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 类型别名配置 -->
<property name="typeAliasesPackage" value="com.zm.domain"/>
<!-- 引入加载 mybatis 的核心配置文件,可以不用去加载 -->
<!-- <property name="configLocation" value="classpath:SqlMapConfig.xml"/>-->
</bean>
<!-- mapper 映射扫描 MapperScannerConfigurer 扫描该包下所有接口,生成代理对象存到 IOC 容器中 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.zm.dao"/>
</bean>
<!-- spring 整合 mybatis 结束 -->
</beans>
修改 AccountServiceImpl
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
AccountDao accountDao;
@Override
public List<Account> findAll() {
return accountDao.findAll();
}
}
测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class SpringTest {
@Autowired
private AccountService accountService;
@Test
public void testSpring() {
System.out.println(accountService.findAll());
}
}
6. 编写 SpringMVC 在 SSM 环境中可以单独使用
需求:访问到 Controller 里面的方法查询所有账户,并跳转到 list.jsp 页面进行列表展示。
相关坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
导入页面资源
在 webapp 目录下导入 JSP 页面相关的资源:add.jsp、index.jsp、list.jsp、update.jsp
index.jsp
...
<div align="center">
<a href="account/findAll" style="text-decoration:none;font-size:33px">
查询账户信息列表
</a>
</div>
...
前端控制器 DispatcherServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!-- 前端控制器 -->
<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>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 中文乱码过滤器:解决 post 方式提交的乱码 -->
<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>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
AccountController
@Controller
@RequestMapping("/account")
public class AccountController {
@RequestMapping("/findAll")
public String findAll(Model model) {
ArrayList<Object> arrayList = new ArrayList<>();
arrayList.add(new Account(1, "张三", 1000d));
arrayList.add(new Account(2, "李四", 2000d));
model.addAttribute("list", arrayList);
return "list";
}
}
list.jsp
···
<c:forEach items="${list}" var="account">
<tr>
<td>
<input type="checkbox" name="ids" value="${account.id}">
</td>
<td>${account.id}</td>
<td>${account.name}</td>
<td>${account.money}</td>
<td>
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/update.jsp">修改</a>
<a class="btn btn-default btn-sm" href="">删除</a>
</td>
</tr>
</c:forEach>
...
SpringMVC 核心配置文件:spring-mvc.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 1. 组件扫描:只扫描 controller -->
<context:component-scan base-package="com.zm.controller"/>
<!-- 2. mvc 注解增强:处理器映射器及处理器适配器 -->
<mvc:annotation-driven/>
<!-- 3. 视图解析器 -->
<bean id="resourceViewResolve" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 4. 放行静态资源 -->
<mvc:default-servlet-handler/>
</beans>
7. Spring 整合 SpringMVC
整合思想
Spring 和 SpringMVC 本来就已经整合好了,都是属于 Spring 全家桶一部分。
但是需要做到 Spring 和 web 容器整合,让 web 容器启动的时候自动加载 Spring 配置文件,web 容 器销毁的时候 Spring 的 IOC 容器也销毁。
Spring 和 Web 容器整合
ContextLoaderListener 加载
可以使用 spring-web 包中的 ContextLoaderListener 监听器,来监听 servletContext 容器的创建和销毁,来同时创建或销毁 IOC 容器。
web.xml
<!-- 配置 spring 的监听器 -->
<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>
修改 AccountController
@Controller
@RequestMapping("/account")
public class AccountController {
@Autowired
private AccountService accountService;
@RequestMapping("/findAll")
public String findAll(Model model) {
model.addAttribute("list", accountService.findAll());
return "list";
}
}
8. Spring 配置声明式事务
Spring 配置文件加入声明式事务
applicationContext.xml
<!-- 1. 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2. 开始事务注解的支持 -->
<tx:annotation-driven/>
AccountServiceImpl 实现类
@Service
@Transactional
public class AccountServiceImpl implements AccountService {
...
}
add.jsp
...
<form action="${pageContext.request.contextPath}/account/save" method="post">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
</div>
<div class="form-group">
<label for="money">余额:</label>
<input type="text" class="form-control" id="money" name="money" placeholder="请输入余额">
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交"/>
<input class="btn btn-default" type="reset" value="重置"/>
<input class="btn btn-default" type="button" onclick="history.go(-1)" value="返回"/>
</div>
</form>
...
AccountDao
void save(Account account);
AccountDao.xml 映射
<insert id="save" parameterType="account">
insert into account (`name`, `money`) values (#{name}, #{money});
</insert>
AccountService 接口和实现类
···
void save(Account account);
···
···
@Override
public void save(Account account) {
accountDao.save(account);
}
···
AccountController
@RequestMapping("/save")
public String save(Account account) {
accountService.save(account);
// 跳转到 findAll 方法重新查询一次数据库进行数据的遍历展示
return "redirect:/account/findAll";
}
9. 修改操作
数据回显
AccountController
@RequestMapping("/findById")
public String findById(Integer id,Model model){
// 存到 model 中
model.addAttribute("account", accountService.findById(id));
// 视图跳转
return "update";
}
AccountService 接口和实现类
···
Account findById(Integer id);
···
@Override
public Account findById(Integer id) {
return accountDao.findById(id);
}
···
AccountDao 接口和 AccountDao.xml 映射文件
···
Account findById(Integer id);
···
···
<select id="findById" parameterType="int" resultType="account">
select * from account where id = #{id}
</select>
update.jsp
...
<form action="${pageContext.request.contextPath}/account/update" method="post">
<input type="hidden" name="id" value="${account.id}">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" value="${account.name}" placeholder="请输入姓名">
</div>
<div class="form-group">
<label for="money">余额:</label>
<input type="text" class="form-control" id="money" name="money" value="${account.money}"placeholder="请输入余额">
</div>
<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交"/>
<input class="btn btn-default" type="reset" value="重置"/>
<input class="btn btn-default" type="button" onclick="history.go(-1)" value="返回"/>
</div>
</form>
...
list.jsp
...
<td>
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/account/findById?id=${account.id}">修改</a>
<a class="btn btn-default btn-sm" href="">删除</a>
</td>
...
账户更新
AccountController
@RequestMapping("/update")
public String update(Account account) {
accountService.update(account);
return "redirect:/account/findAll";
}
AccountService 接口和实现类
···
void update(Account account);
···
···
@Override
public void update(Account account) {
accountDao.update(account);
}
···
AccountDao 接口和 AccountDao.xml 映射文件
···
void update(Account account);
···
···
<update id="update" parameterType="account">
update account set name = #{name}, money = #{money} where id = #{id}
</update>
···
10. 批量删除
list.jsp
<form action="${pageContext.request.contextPath}/account/deleteBatch" method="post" id="deleteBatchForm">
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>
<input type="checkbox" id="checkAll">
</th>
<th>编号</th>
<th>姓名</th>
<th>余额</th>
<th>操作</th>
</tr>
<c:forEach items="${list}" var="account">
<tr>
<td>
<input type="checkbox" name="ids" value="${account.id}">
</td>
<td>${account.id}</td>
<td>${account.name}</td>
<td>${account.money}</td>
<td>
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/account/findById?id=${account.id}">
修改
</a>
<a class="btn btn-default btn-sm" href="">
删除
</a>
</td>
</tr>
</c:forEach>
<tr>
<td colspan="9" align="center">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/add.jsp">添加账户</a>
<input class="btn btn-primary" type="button" value="删除选中" id="deleteBatchBtn">
</td>
</tr>
</table>
</form>
...
<script>
/* 实现全选全不选效果 */
$('#checkAll').click(function () {
$('input[name="ids"]').prop('checked', $(this).prop('checked'));
});
/* 给删除选中按钮绑定点击事件 */
$('#deleteBatchBtn').click(function () {
if (confirm('确定要删除吗')) {
if ($('input[name=ids]:checked').length > 0) {
/* 提交表单 */
$('#deleteBatchForm').submit();
}
} else {
alert('操作被取消')
}
});
</script>
...
AccountController
@RequestMapping("/deleteBatch")
public String deleteBatch(Integer[] ids) {
accountService.deleteBatch(ids);
return "redirect:/account/findAll";
}
AccountService 接口和实现类
void deleteBatch(Integer[] ids);
@Override
public void deleteBatch(Integer[] ids) {
accountDao.deleteBatch(ids);
}
AccountDao 接口和 AccountDao.xml 映射文件
void deleteBatch(Integer[] ids);
<delete id="deleteBatch" parameterType="int">
delete from account
<where>
<foreach collection="array" open="id in(" close=")" separator="," item="id">
#{id}
</foreach>
</where>
</delete>边栏推荐
- Pytorch learning diary (4)
- I heard that today's blog can get a badge!
- 剑指Offer刷题记录——Offer 04. 二维数组中的查找
- Crawler Basics - session and cookies
- Data analysis and visualization -- the shoes with the highest sales volume on jd.com
- 网络知识-03 数据链路层-以太网
- MySQL正则表达式^和$用法
- express
- TypeScript(ts-loader,tsconfig.json及lodash)
- The principle of SYN Flood attack and the solution of SYN Flood Attack
猜你喜欢

Matlab implementation code of image denoising method based on Hidden Markov tree model in wavelet domain

Paper reading: deep residual shrink networks for fault diagnosis

m3GPP-LTE通信网络中认知家庭网络Cognitive-femtocell性能matlab仿真

103.53.124. What is the difference between X IP BGP line and ordinary dedicated line

How to output a digital diamond with a for loop

网络知识-02 物理层

基于simulink的转速反馈单闭环直流调速系统

Sword finger offer question brushing record - offer 07 Rebuild binary tree

论文阅读:Deep Residual Shrinkage Networksfor Fault Diagnosis

Network knowledge-04 network layer ICMP Protocol
随机推荐
Data protection / disk array raid protection IP segment 103.103.188 xxx
Filter过滤器
Pycharm安装教程
How do you know whether the network needs to use advanced anti DDoS server? How to choose the computer room is also very important, as well as the stability of the later business
Use of urllib Library
FreeBSD 12 domestic source speed up PKG and ports take a note
Speed feedback single closed loop DC speed regulation system based on Simulink
103.53.124. What is the difference between X IP BGP line and ordinary dedicated line
剑指Offer刷题记录——Offer 03. 数组中重复的数字
网络知识-03 数据链路层-PPPoE
How to output a digital diamond with a for loop
Pytorch learning diary (4)
Execute shell script under Linux to call SQL file and transfer it to remote server
[untitled]
Steam game high frequency i9-12900k build cs:go server
Network knowledge-04 network layer IPv4 protocol
Paper reading: deep residual learning in spiking neural networks
m基于matlab的BTS天线设计,带GUI界面
C语言编译器的下载、配置和基本使用
What does IP fragment mean? How to defend against IP fragment attacks?