企业信息管理系统开发实战:基于 Spring Boot+MyBatis+Thymeleaf

引言:企业信息管理系统的核心价值

在企业日常运营中,高效的信息管理是提升效率的关键。本文将手把手教你开发一套企业信息管理系统,涵盖用户登录、信息增删改查、权限控制等核心功能。系统采用 Spring Boot 作为后端框架,MyBatis 处理数据交互,Thymeleaf 实现前端页面渲染,Druid 作为数据源保障性能,最终形成一套轻量、易用、可扩展的企业级解决方案。

一、系统架构与技术栈

1.1 系统功能概述

本系统聚焦企业用户信息管理,核心功能包括:

  • 用户登录 / 退出(含权限拦截)
  • 用户信息列表展示
  • 用户信息添加、修改、删除
  • 前端页面动态渲染与交互

1.2 技术栈选择

  • 后端:Spring Boot 3.2.8(框架核心)、MyBatis 3.0.3(ORM 框架)、Druid 1.2.20(数据源)
  • 前端:Thymeleaf 3.1.2(模板引擎)、HTML5/CSS3(页面结构与样式)、jQuery 3.7.1(前端交互)
  • 数据库:MySQL 8.0(数据存储)
  • 开发工具:IntelliJ IDEA、Maven(依赖管理)

二、环境搭建与项目初始化

2.1 数据库设计

首先创建系统所需的数据库表,以my_user表为例(存储用户信息):

sql 复制代码
SET FOREIGN_KEY_CHECKS=0;

-- 用户表结构
DROP TABLE IF EXISTS `my_user`;
CREATE TABLE `my_user` (
  `pid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `username` varchar(255) DEFAULT NULL COMMENT '用户名',
  `password` varchar(255) DEFAULT NULL COMMENT '密码',
  `p_addr` varchar(255) DEFAULT NULL COMMENT '地址(下划线命名)',
  `gender` int(11) DEFAULT NULL COMMENT '性别(1-男,0-女)',
  `birth` date DEFAULT NULL COMMENT '生日',
  PRIMARY KEY (`pid`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户信息表';

-- 初始化测试数据
INSERT INTO `my_user` VALUES (1, 'zhangsan', '123', '北京', 1, '2020-06-14');

2.2 项目结构设计

遵循 Spring Boot 最佳实践,项目结构如下:

复制代码
src/
├── main/
│   ├── java/com/qcby/inforcontrollersystem/
│   │   ├── config/           # 配置类(Druid、MyBatis、MVC等)
│   │   ├── controller/       # 控制器(处理请求)
│   │   ├── entity/           # 实体类(与数据库表映射)
│   │   ├── interceptor/      # 拦截器(登录验证等)
│   │   ├── mapper/           # MyBatis映射接口
│   │   ├── service/          # 业务逻辑层(含Impl实现)
│   │   └── InforControllerSystemApplication.java  # 启动类
│   ├── resources/
│   │   ├── application.yaml  # 主配置文件
│   │   ├── static/           # 静态资源(css、images、js)
│   │   └── templates/        # Thymeleaf模板(login.html、main.html等)
└── test/                      # 单元测试目录

2.3 核心依赖配置(pom.xml)

通过 Maven 管理依赖,关键依赖如下:

XML 复制代码
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.8</version>
</parent>

<dependencies>
    <!-- Spring Boot Web核心 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Thymeleaf模板引擎 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- MyBatis整合 -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>3.0.3</version>
    </dependency>

    <!-- Druid数据源(适配Spring Boot 3) -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-3-starter</artifactId>
        <version>1.2.20</version>
    </dependency>

    <!-- MySQL驱动 -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- jQuery(WebJars方式) -->
    <dependency>
        <groupId>org.webjars</groupId>
        <artifactId>jquery</artifactId>
        <version>3.7.1</version>
    </dependency>

    <!-- 测试依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

三、核心配置详解

3.1 数据源配置(Druid)

Druid 作为高性能数据源,需配置连接池参数和监控功能,创建DruidConfig.java

java 复制代码
package com.qcby.inforcontrollersystem.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class DruidConfig {
    // 绑定application.yaml中spring.datasource前缀的配置
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }
}

3.2 MyBatis 配置(解决驼峰映射)

数据库表字段采用下划线命名(如p_addr),实体类采用驼峰命名(如pAddr),需配置映射规则:

java 复制代码
package com.qcby.inforcontrollersystem.config;

import org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisConfig {
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        // 开启下划线转驼峰映射
        return configuration -> configuration.setMapUnderscoreToCamelCase(true);
    }
}

3.3 MVC 配置(视图映射与拦截器)

配置页面路由和登录拦截器,确保未登录用户无法访问核心功能:

java 复制代码
package com.qcby.inforcontrollersystem.config;

import com.qcby.inforcontrollersystem.interceptor.LoginInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

@Configuration
@MapperScan("com.qcby.inforcontrollersystem.mapper") // 扫描MyBatis Mapper接口
public class TxMvcConfig implements WebMvcConfigurer {

    // 视图映射:直接将请求路径映射到模板页面
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/toLogin").setViewName("login"); // /toLogin -> login.html
        registry.addViewController("/index").setViewName("index");   // /index -> index.html
        registry.addViewController("/menu").setViewName("menu");     // /menu -> menu.html
    }

    // 注册拦截器:拦截未登录用户
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> excludePaths = new ArrayList<>();
        // 排除登录页、静态资源等不需要拦截的路径
        excludePaths.add("/css/**");
        excludePaths.add("/images/**");
        excludePaths.add("/toLogin");
        excludePaths.add("/login");

        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns(excludePaths); // 排除指定路径
    }
}

四、核心功能实现

4.1 实体类设计(MyUser.java)

my_user表映射,包含用户基本信息:

java 复制代码
package com.qcby.inforcontrollersystem.entity;

import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;

public class MyUser {
    private Integer pid;         // 主键
    private String username;     // 用户名
    private String password;     // 密码
    private String pAddr;        // 地址(驼峰命名,对应表中p_addr)
    private Integer gender;      // 性别
    @DateTimeFormat(pattern = "yyyy-MM-dd") // 日期格式转换
    private Date birth;          // 生日

    // 构造方法、Getter、Setter(省略,需手动生成)
}

4.2 登录拦截器(LoginInterceptor.java)

拦截未登录用户,强制跳转至登录页:

java 复制代码
package com.qcby.inforcontrollersystem.interceptor;

import com.qcby.inforcontrollersystem.entity.MyUser;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        MyUser user = (MyUser) session.getAttribute("user"); // 从Session获取用户信息

        if (user == null) {
            // 未登录,重定向到登录页
            response.sendRedirect(request.getContextPath() + "/toLogin");
            return false;
        }
        // 已登录,放行
        return true;
    }
}

4.3 数据访问层(Mapper 接口)

通过 MyBatis 注解实现数据库操作:

java 复制代码
package com.qcby.inforcontrollersystem.mapper;

import com.qcby.inforcontrollersystem.entity.MyUser;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;

public interface MyUserMapper {
    // 新增用户(自增主键回写)
    @Options(useGeneratedKeys = true, keyProperty = "pid")
    @Insert("insert into my_user(username, password, p_addr, gender, birth) " +
            "values(#{username}, #{password}, #{pAddr}, #{gender}, #{birth})")
    void insert(MyUser user);

    // 查询所有用户
    @Select("select * from my_user")
    List<MyUser> selectUsers();

    // 登录验证(根据用户名和密码查询)
    @Select("select * from my_user where username = #{username} and password = #{password}")
    MyUser selectUsersByUsernameAndPassword(Map<String, String> map);

    // 根据ID查询用户(用于修改)
    @Select("select * from my_user where pid = #{pid}")
    MyUser selectUserById(int pid);

    // 更新用户信息
    @Update("update my_user set username=#{username}, password=#{password}, p_addr=#{pAddr}, " +
            "gender=#{gender}, birth=#{birth} where pid=#{pid}")
    void update(MyUser user);

    // 删除用户
    @Delete("delete from my_user where pid = #{pid}")
    void delete(int pid);
}

4.4 业务逻辑层(Service)

封装业务逻辑,调用 Mapper 接口:

java 复制代码
// 接口定义
package com.qcby.inforcontrollersystem.service;

import com.qcby.inforcontrollersystem.entity.MyUser;
import java.util.List;
import java.util.Map;

public interface MyUserService {
    void insert(MyUser user);
    List<MyUser> selectUsers();
    MyUser selectUsersByUsernameAndPassword(Map<String, String> map);
    MyUser selectUserById(int pid);
    void update(MyUser user);
    void delete(int pid);
}

// 实现类
package com.qcby.inforcontrollersystem.service.Impl;

import com.qcby.inforcontrollersystem.entity.MyUser;
import com.qcby.inforcontrollersystem.mapper.MyUserMapper;
import com.qcby.inforcontrollersystem.service.MyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;

@Service
@Transactional // 开启事务管理
public class MyUserServiceImpl implements MyUserService {
    @Autowired
    private MyUserMapper userMapper;

    @Override
    public void insert(MyUser user) {
        userMapper.insert(user);
    }

    @Override
    public List<MyUser> selectUsers() {
        return userMapper.selectUsers();
    }

    @Override
    public MyUser selectUsersByUsernameAndPassword(Map<String, String> map) {
        return userMapper.selectUsersByUsernameAndPassword(map);
    }

    @Override
    public MyUser selectUserById(int pid) {
        return userMapper.selectUserById(pid);
    }

    @Override
    public void update(MyUser user) {
        userMapper.update(user);
    }

    @Override
    public void delete(int pid) {
        userMapper.delete(pid);
    }
}

4.5 控制器(Controller)

处理前端请求,协调视图与数据:

(1)登录控制器(LoginController.java)
java 复制代码
package com.qcby.inforcontrollersystem.controller;

import com.qcby.inforcontrollersystem.entity.MyUser;
import com.qcby.inforcontrollersystem.service.MyUserService;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.HashMap;
import java.util.Map;

@Controller
public class LoginController {
    @Autowired
    private MyUserService myUserService;

    // 跳转到登录页
    @GetMapping("/toLogin")
    public String toLogin() {
        return "login";
    }

    // 处理登录请求
    @PostMapping("/login")
    public String login(HttpSession session, String username, String password, Model model) {
        Map<String, String> map = new HashMap<>();
        map.put("username", username);
        map.put("password", password);
        MyUser user = myUserService.selectUsersByUsernameAndPassword(map);

        if (user != null) {
            // 登录成功,将用户信息存入Session
            session.setAttribute("user", user);
            return "redirect:/index"; // 重定向到首页
        } else {
            // 登录失败,回显错误信息
            model.addAttribute("tip", "用户名或密码错误");
            return "login";
        }
    }

    // 退出登录
    @GetMapping("/logout")
    public String logout(HttpSession session) {
        session.invalidate(); // 清除Session
        return "redirect:/toLogin";
    }
}
(2)用户管理控制器(UserController.java)
java 复制代码
package com.qcby.inforcontrollersystem.controller;

import com.qcby.inforcontrollersystem.entity.MyUser;
import com.qcby.inforcontrollersystem.service.MyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

@Controller
public class UserController {
    @Autowired
    private MyUserService myUserService;

    // 展示用户列表
    @GetMapping("/main")
    public String showUserList(Model model) {
        List<MyUser> users = myUserService.selectUsers();
        model.addAttribute("users", users); // 存入模型,供前端渲染
        return "main";
    }

    // 跳转到添加用户页面
    @GetMapping("/add")
    public String toAddPage() {
        return "add";
    }

    // 保存新用户
    @PostMapping("/save")
    public String saveUser(MyUser user, @RequestParam String birth) {
        try {
            // 转换日期格式(前端传递字符串,需转为Date)
            if (birth != null && !birth.isEmpty()) {
                user.setBirth(new SimpleDateFormat("yyyy-MM-dd").parse(birth));
            }
            myUserService.insert(user);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return "redirect:/main"; // 重定向到列表页
    }

    // 跳转到修改页面(携带用户ID)
    @GetMapping("/getUser")
    public String toUpdatePage(@RequestParam int pid, Model model) {
        MyUser user = myUserService.selectUserById(pid);
        model.addAttribute("user", user); // 回显用户信息
        return "update";
    }

    // 更新用户信息
    @PostMapping("/update")
    public String updateUser(MyUser user, @RequestParam String birth) {
        try {
            if (birth != null && !birth.isEmpty()) {
                user.setBirth(new SimpleDateFormat("yyyy-MM-dd").parse(birth));
            }
            myUserService.update(user);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return "redirect:/main";
    }

    // 删除用户
    @GetMapping("/delete")
    public String deleteUser(@RequestParam int pid) {
        myUserService.delete(pid);
        return "redirect:/main";
    }
}

五、前端页面实现(Thymeleaf 模板)

5.1 登录页(login.html)

html 复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
    <link th:href="@{/css/login.css}" rel="stylesheet"> <!-- 引入CSS -->
    <script th:src="@{/webjars/jquery/3.7.1/jquery.min.js}"></script> <!-- 引入jQuery -->
    <script>
        // 登录表单验证
        function login1() {
            const username = $("input[name='username']").val().trim();
            const password = $("input[name='password']").val().trim();
            if (!username) {
                alert("请输入用户名");
                return;
            }
            if (!password) {
                alert("请输入密码");
                return;
            }
            $("form").submit(); // 提交表单
        }
    </script>
</head>
<body>
<div id="login">
    <div id="top">
        <div id="top_left"><img th:src="@{/images/login_03.gif}" alt="系统Logo"></div>
    </div>
    <form th:action="@{/login}" method="post">
        <div id="center">
            <div id="center_middle">
                <!-- 登录错误提示 -->
                <div style="color: red; text-align: center" th:text="${tip}"></div>
                <div id="user">
                    用户名:<input type="text" name="username" placeholder="请输入用户名">
                </div>
                <div id="password">
                    密码:<input type="password" name="password" placeholder="请输入密码">
                </div>
                <div id="btn">
                    <a href="#" onclick="login1()">登录</a>
                    <a href="#" onclick="$('form')[0].reset()">清空</a>
                </div>
            </div>
        </div>
    </form>
</div>
</body>
</html>

5.2 用户列表页(main.html)

html 复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户列表</title>
    <style>
        .mt { margin: 20px auto; width: 90%; border-collapse: collapse; }
        .mt th, .mt td { border: 1px solid #ddd; padding: 10px; text-align: center; }
        .add-btn { margin: 20px 0 0 5%; padding: 6px 12px; background: #4CAF50; color: white; text-decoration: none; }
    </style>
</head>
<body>
<!-- 添加用户按钮 -->
<a th:href="@{/add}" class="add-btn">添加用户</a>

<!-- 用户列表表格 -->
<table class="mt">
    <tr>
        <th>用户名</th>
        <th>密码</th>
        <th>地址</th>
        <th>性别</th>
        <th>生日</th>
        <th>操作</th>
    </tr>
    <!-- 遍历用户列表(Thymeleaf语法) -->
    <tr th:each="user : ${users}">
        <td th:text="${user.username}"></td>
        <td th:text="${user.password}"></td>
        <td th:text="${user.pAddr}"></td>
        <td th:text="${user.gender == 1 ? '男' : '女'}"></td> <!-- 性别转换 -->
        <td th:text="${#calendars.format(user.birth, 'yyyy-MM-dd')}"></td> <!-- 日期格式化 -->
        <td>
            <a th:href="@{/getUser(pid=${user.pid})}">修改</a>
            <a th:href="@{/delete(pid=${user.pid})}" onclick="return confirm('确定删除?')">删除</a>
        </td>
    </tr>
</table>
</body>
</html>

5.3 添加用户页(add.html)

html 复制代码
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>添加用户</title>
    <style>
        .mt { margin: 30px auto; border-collapse: collapse; }
        .mt td { padding: 10px; }
        input { padding: 6px; width: 250px; }
    </style>
</head>
<body>
<form th:action="@{/save}" method="post">
    <table class="mt">
        <tr>
            <td>用户名</td>
            <td><input type="text" name="username" required></td>
        </tr>
        <tr>
            <td>密码</td>
            <td><input type="password" name="password" required></td>
        </tr>
        <tr>
            <td>地址</td>
            <td><input type="text" name="pAddr"></td>
        </tr>
        <tr>
            <td>性别</td>
            <td>
                <input type="radio" name="gender" value="1" checked>男
                <input type="radio" name="gender" value="0">女
            </td>
        </tr>
        <tr>
            <td>生日</td>
            <td><input type="date" name="birth"></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="保存"></td>
        </tr>
    </table>
</form>
</body>
</html>

六、系统配置文件(application.yaml)

统一配置数据源、MyBatis 等参数:

复制代码
spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/boot_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    # Druid连接池参数
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT 1 FROM DUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    filters: stat,wall  # 开启监控和防火墙

# MyBatis配置
mybatis:
  mapper-locations: classpath:mapper/*.xml  # 若使用XML映射,需指定路径
  type-aliases-package: com.qcby.inforcontrollersystem.entity  # 实体类别名

七、系统测试与运行

  1. 启动项目 :运行InforControllerSystemApplication.javamain方法,Spring Boot 内置 Tomcat 启动,默认端口 8080。
  2. 访问登录页 :浏览器输入http://localhost:8080/toLogin,使用初始化数据(用户名zhangsan,密码123)登录。
  3. 功能验证
    • 登录成功后跳转至首页,展示用户列表;
    • 点击 "添加用户",填写信息后保存,列表页会新增记录;
    • 点击 "修改" 可更新用户信息,点击 "删除" 可移除记录;
    • 未登录时直接访问/main会被拦截,强制跳转至登录页。

相关推荐
rannn_111几秒前
【MySQL学习|黑马笔记|Day3】多表查询(多表关系、内连接、外连接、自连接、联合查询、子查询),事务(简介、操作、四大体系、并发事务问题、事务隔离级别)
数据库·笔记·后端·学习·mysql
Java中文社群33 分钟前
不要傻呵呵等金九银十了!
java·后端·面试
SimonKing1 小时前
手撕「字段自动填充」的2种方案
java·后端·程序员
青梅主码1 小时前
介绍一下我开发的:经典蜘蛛纸牌的网页免费游戏
后端
转转技术团队1 小时前
打造亿级流量开放平台的架构演进与工程实战
后端·微服务·架构
斜月1 小时前
订单系统的设计和实现实践
java·后端
_风不会停息1 小时前
RocketMQ 启动过程分析&大流量场景优化
后端·rocketmq
Abadbeginning1 小时前
FastSoyAdmin 准备篇
后端
微笑听雨1 小时前
基于 Drools 的规则引擎性能调优实践:架构、缓存与编译优化全解析
java·后端
五岁小孩吖2 小时前
实操使用 go pprof 对生产环境进行性能分析(问题定位及代码优化)
后端