SpringMVC 实战:整合 MyBatis 实现完整 CRUD - 实践
引言
前面两篇我们掌握了 SpringMVC 的基础和进阶技术,但实际项目中,SpringMVC 很少单独使用,通常需要与持久层框架(如 MyBatis)整合,实现 “接收请求→业务处理→操作数据库→返回结果” 的完整流程。本文将带你从零搭建 “SpringMVC + MyBatis” 的项目,实现用户管理的 CRUD 功能,覆盖实际开发中的核心配置和最佳实践。
一、整合思路与技术栈
1. 技术栈选型
| 技术 | 版本 | 作用 |
|---|---|---|
| SpringMVC | 5.3.28 | 控制层,接收请求、返回视图 |
| Spring | 5.3.28 | 核心容器,管理 Service、DAOBean |
| MyBatis | 3.5.13 | 持久层,操作数据库 |
| MyBatis-Spring | 2.1.2 | 整合 Spring 与 MyBatis |
| MySQL | 8.0 | 数据库 |
| Druid | 1.2.16 | 数据库连接池(高效、安全) |
| JSP + JSTL | JSP 2.2 | 前端视图 |
| Maven | 3.8 | 项目构建与依赖管理 |
| Tomcat | 9.0 | 服务器 |
2. 整合核心思路
采用 “分层架构”,各层职责清晰,通过 Spring 的 IOC 容器整合各层 Bean:
- Controller 层(SpringMVC):接收请求,调用 Service 层;
- Service 层(Spring):处理业务逻辑,调用 DAO 层,管理事务;
- DAO 层(MyBatis):定义数据访问接口,MyBatis 实现 SQL 操作;
- Spring 容器:
- 父容器(
spring.xml):管理 Service、DAO、数据源等非 Web 组件; - 子容器(
spring-mvc.xml):管理 Controller 组件,子容器可访问父容器的 Bean,反之不行。
- 父容器(
二、环境搭建:从零开始配置
1. 步骤 1:创建 Maven Web 项目
同博客一的 “步骤 1”,项目名改为springmvc-mybatis-crud。
2. 步骤 2:导入整合依赖(pom.xml)
核心依赖包括 Spring、SpringMVC、MyBatis、MyBatis-Spring、MySQL 驱动、Druid 连接池:
xml
org.springframework
spring-context
5.3.28
org.springframework
spring-jdbc
5.3.28
org.springframework
spring-webmvc
5.3.28
org.mybatis
mybatis
3.5.13
org.mybatis
mybatis-spring
2.1.2
mysql
mysql-connector-java
8.0.33
com.alibaba
druid
1.2.16
javax.servlet
javax.servlet-api
4.0.1
provided
javax.servlet.jsp.jstl
jstl-api
1.2
taglibs
standard
1.1.2
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
1.8
UTF-8
3. 步骤 3:配置 web.xml(整合核心)
web.xml需配置 3 个关键内容:Spring 父容器初始化、SpringMVC 前端控制器、编码过滤器:
xml
characterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
UTF-8
forceEncoding
true
characterEncodingFilter
/*
contextConfigLocation
classpath:spring.xml
org.springframework.web.context.ContextLoaderListener
springmvc
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
springmvc
/
4. 步骤 4:配置 Spring 父容器(spring.xml)
spring.xml主要配置:数据源、SqlSessionFactory、DAO 扫描、Service 扫描、事务管理。
(1)配置数据源(Druid)
xml
(2)配置 SqlSessionFactory(MyBatis 核心)
xml
(3)配置 DAO 接口扫描(MyBatis-Spring)
xml
(4)配置 Service 扫描与事务管理
xml
5. 步骤 5:配置 MyBatis 全局文件(mybatis-config.xml)
MyBatis 全局配置主要用于设置 “日志、缓存” 等,简化版配置如下:
xml
6. 步骤 6:配置 SpringMVC 子容器(spring-mvc.xml)
spring-mvc.xml配置Controller 扫描、注解驱动、视图解析器、静态资源处理:
xml
7. 步骤 7:创建数据库表(MySQL)
创建user表,用于存储用户信息:
sql
CREATE DATABASE IF NOT EXISTS springmvc_mybatis;
USE springmvc_mybatis;
CREATE TABLE IF NOT EXISTS `user` (
`id` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL,
`age` INT,
`email` VARCHAR(100)
);
-- 插入测试数据
INSERT INTO `user` (`username`, `age`, `email`) VALUES
('张三', 20, 'zhangsan@xxx.com'),
('李四', 25, 'lisi@xxx.com');
8. 步骤 8:创建 db.properties(数据库配置)
在resources目录下新建db.properties,存储数据库连接信息(避免硬编码):
properties
# MySQL 8.0+驱动类
db.driver=com.mysql.cj.jdbc.Driver
# URL(useSSL=false:禁用SSL;serverTimezone=UTC:设置时区)
db.url=jdbc:mysql://localhost:3306/springmvc_mybatis?useSSL=false&serverTimezone=UTC&characterEncoding=UTF-8
# 数据库用户名(替换为你的)
db.username=root
# 数据库密码(替换为你的)
db.password=123456
三、实现 CRUD 功能:分层开发
1. 项目结构梳理
先明确各层的包结构(在src/main/java下):
plaintext
com.example
├── controller # 控制层(UserController)
├── service # 业务层(UserService接口 + UserServiceImpl实现)
├── dao # 数据访问层(UserDao接口)
└── pojo # 实体类(User)
在resources目录下:
plaintext
resources
├── db.properties # 数据库配置
├── spring.xml # Spring父容器配置
├── spring-mvc.xml # SpringMVC子容器配置
├── mybatis-config.xml # MyBatis全局配置
└── mapper # MyBatis Mapper XML(UserMapper.xml)
在WEB-INF下:
plaintext
WEB-INF
├── views # JSP视图
│ ├── user
│ │ ├── list.jsp # 用户列表页
│ │ ├── add.jsp # 添加用户页
│ │ └── edit.jsp # 编辑用户页
│ └── success.jsp # 操作成功页
└── web.xml # Web配置
2. 步骤 1:编写 POJO 实体类(User.java)
java
运行
package com.example.pojo;
public class User {
private Integer id;
private String username;
private Integer age;
private String email;
// 默认无参构造器
public User() {}
// 带参构造器(可选)
public User(String username, Integer age, String email) {
this.username = username;
this.age = age;
this.email = email;
}
// Getter和Setter方法(必须)
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 Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
// toString方法(方便打印)
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
}
3. 步骤 2:编写 DAO 层(UserDao 接口 + UserMapper.xml)
(1)UserDao 接口(无需实现类,MyBatis 动态代理)
java
运行
package com.example.dao;
import com.example.pojo.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface UserDao {
// 1. 查询所有用户
List findAll();
// 2. 根据ID查询用户
User findById(@Param("id") Integer id); // @Param:指定SQL中的参数名
// 3. 添加用户
void addUser(User user);
// 4. 更新用户
void updateUser(User user);
// 5. 删除用户
void deleteUser(@Param("id") Integer id);
}
(2)UserMapper.xml(MyBatis SQL 实现)
在resources/mapper目录下新建UserMapper.xml:
xml
INSERT INTO user (username, age, email) VALUES (#{username}, #{age}, #{email})
UPDATE user SET username = #{username}, age = #{age}, email = #{email} WHERE id = #{id}
DELETE FROM user WHERE id = #{id}
4. 步骤 3:编写 Service 层(UserService 接口 + UserServiceImpl 实现)
(1)UserService 接口
java
运行
package com.example.service;
import com.example.pojo.User;
import java.util.List;
public interface UserService {
// 1. 查询所有用户
List findAllUsers();
// 2. 根据ID查询用户
User findUserById(Integer id);
// 3. 添加用户
void addUser(User user);
// 4. 更新用户
void updateUser(User user);
// 5. 删除用户
void deleteUser(Integer id);
}
(2)UserServiceImpl 实现类(注入 DAO,处理事务)
java
运行
package com.example.service.impl;
import com.example.dao.UserDao;
import com.example.pojo.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service // 标记为Service组件,交给Spring管理
@Transactional // 开启事务(所有方法都受事务管理)
public class UserServiceImpl implements UserService {
// 注入UserDao(MyBatis动态代理生成的实现类)
@Autowired
private UserDao userDao;
@Override
public List findAllUsers() {
return userDao.findAll();
}
@Override
public User findUserById(Integer id) {
return userDao.findById(id);
}
@Override
public void addUser(User user) {
userDao.addUser(user);
}
@Override
public void updateUser(User user) {
userDao.updateUser(user);
}
@Override
public void deleteUser(Integer id) {
userDao.deleteUser(id);
}
}
5. 步骤 4:编写 Controller 层(UserController)
处理用户相关的 5 个请求:查询所有、查询单个、添加、编辑、删除。
java
运行
package com.example.controller;
import com.example.pojo.User;
import com.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.List;
@Controller
@RequestMapping("/user") // 类级别的请求映射,所有方法路径都以/user开头
public class UserController {
// 注入UserService(Spring父容器的Bean,子容器可访问)
@Autowired
private UserService userService;
// 1. 查询所有用户(跳转到列表页)
@RequestMapping("/list")
public String findAll(Model model) {
List userList = userService.findAllUsers();
model.addAttribute("userList", userList); // 存入Model,供JSP使用
return "user/list"; // 跳转到user/list.jsp
}
// 2. 跳转到添加用户页面
@RequestMapping("/toAdd")
public String toAdd() {
return "user/add"; // 跳转到user/add.jsp
}
// 3. 执行添加用户操作
@RequestMapping("/add")
public String addUser(User user) {
userService.addUser(user);
return "redirect:/user/list"; // 重定向到用户列表页(避免表单重复提交)
}
// 4. 跳转到编辑用户页面(携带用户ID)
@RequestMapping("/toEdit")
public String toEdit(Integer id, Model model) {
User user = userService.findUserById(id);
model.addAttribute("user", user); // 传入编辑页的用户数据
return "user/edit"; // 跳转到user/edit.jsp
}
// 5. 执行更新用户操作
@RequestMapping("/update")
public String updateUser(User user) {
userService.updateUser(user);
return "redirect:/user/list"; // 重定向到列表页
}
// 6. 执行删除用户操作
@RequestMapping("/delete")
public String deleteUser(Integer id) {
userService.deleteUser(id);
return "redirect:/user/list"; // 重定向到列表页
}
}
6. 步骤 5:编写前端 JSP 视图
(1)用户列表页(list.jsp)
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
用户列表
添加用户
ID
用户名
年龄
邮箱
操作
${user.id}
${user.username}
${user.age}
${user.email}
编辑
删除
(2)添加用户页(add.jsp)
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
添加用户
(3)编辑用户页(edit.jsp)
jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
编辑用户
四、测试与运行
1. 部署项目
- 配置 Tomcat(同博客一),将
springmvc-mybatis-crud部署到 Tomcat; - 启动 Tomcat,确保数据库服务已开启。
2. 测试 CRUD 功能
- 访问用户列表页:
http://localhost:8080/springmvc-mybatis-crud/user/list,可看到初始的 2 条测试数据; - 测试 “添加用户”:点击 “添加用户”,填写表单并提交,列表页会显示新添加的用户;
- 测试 “编辑用户”:点击某条数据的 “编辑”,修改信息后提交,列表页数据更新;
- 测试 “删除用户”:点击 “删除”,确认后数据从列表中移除。
五、实战小结与优化建议
核心收获:
- 掌握 “SpringMVC + MyBatis” 的分层整合思路,理解父子容器的关系;
- 学会用 MyBatis-Spring 的
MapperScannerConfigurer简化 DAO 层开发; - 理解 “重定向(redirect)” 避免表单重复提交的原理。
优化建议(实际项目中常用):
- 分页查询:用户数据多时,用 MyBatis 分页插件(如 PageHelper)实现分页;
- 参数校验:用 Hibernate Validator(如
@NotBlank、@Min)替代前端校验,确保数据合法性; - 异常处理:自定义全局异常处理器(实现
HandlerExceptionResolver),统一处理异常; - 前后端分离:将 JSP 替换为 Vue/React,Controller 用
@ResponseBody返回 JSON,提升用户体验。
源码获取:本文完整源码已上传至 GitHub(地址:github.com/xxx/springmvc-mybatis-crud),可直接下载运行。
覆盖了 SpringMVC 的核心知识点和实际应用,你可以根据学习进度逐步阅读和实践。如果在搭建项目或理解知识点时遇到问题,欢迎在评论区交流!
浙公网安备 33010602011771号