SpringMVC 实战:整合 MyBatis 实现完整 CRUD - 实践

引言

前面两篇我们掌握了 SpringMVC 的基础和进阶技术,但实际项目中,SpringMVC 很少单独使用,通常需要与持久层框架(如 MyBatis)整合,实现 “接收请求→业务处理→操作数据库→返回结果” 的完整流程。本文将带你从零搭建 “SpringMVC + MyBatis” 的项目,实现用户管理的 CRUD 功能,覆盖实际开发中的核心配置和最佳实践。

一、整合思路与技术栈

1. 技术栈选型

技术版本作用
SpringMVC5.3.28控制层,接收请求、返回视图
Spring5.3.28核心容器,管理 Service、DAOBean
MyBatis3.5.13持久层,操作数据库
MyBatis-Spring2.1.2整合 Spring 与 MyBatis
MySQL8.0数据库
Druid1.2.16数据库连接池(高效、安全)
JSP + JSTLJSP 2.2前端视图
Maven3.8项目构建与依赖管理
Tomcat9.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主要配置:数据源SqlSessionFactoryDAO 扫描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 条测试数据;
  • 测试 “添加用户”:点击 “添加用户”,填写表单并提交,列表页会显示新添加的用户;
  • 测试 “编辑用户”:点击某条数据的 “编辑”,修改信息后提交,列表页数据更新;
  • 测试 “删除用户”:点击 “删除”,确认后数据从列表中移除。

五、实战小结与优化建议

  1. 核心收获:

    • 掌握 “SpringMVC + MyBatis” 的分层整合思路,理解父子容器的关系;
    • 学会用 MyBatis-Spring 的MapperScannerConfigurer简化 DAO 层开发;
    • 理解 “重定向(redirect)” 避免表单重复提交的原理。
  2. 优化建议(实际项目中常用):

    • 分页查询:用户数据多时,用 MyBatis 分页插件(如 PageHelper)实现分页;
    • 参数校验:用 Hibernate Validator(如@NotBlank@Min)替代前端校验,确保数据合法性;
    • 异常处理:自定义全局异常处理器(实现HandlerExceptionResolver),统一处理异常;
    • 前后端分离:将 JSP 替换为 Vue/React,Controller 用@ResponseBody返回 JSON,提升用户体验。
  3. 源码获取:本文完整源码已上传至 GitHub(地址:github.com/xxx/springmvc-mybatis-crud),可直接下载运行。

覆盖了 SpringMVC 的核心知识点和实际应用,你可以根据学习进度逐步阅读和实践。如果在搭建项目或理解知识点时遇到问题,欢迎在评论区交流!

posted @ 2025-10-14 15:28  ycfenxi  阅读(6)  评论(0)    收藏  举报