1.Maven 创建 Spring Boot 项目:
主要使用 Maven 创建 Spring Boot 项目、配置 MySQL 数据库、回顾 Spring Boot 分层架构、使用 MyBatis 逆向工程生成代码及整合测试项目等内容,具体如下:
- Maven 创建 Spring Boot 项目
- 可通过 IDEA 直接创建,高版本 IDEA 若想使用低版本 JDK,也可借助阿里云国服地址(https://start.aliyun.com/)间接创建,创建时可预先选择如 MySQL 驱动、Spring Web 等必要依赖。
- 项目创建成功后,运行时若出现数据库连接错误,可先注释屏蔽 pom.xml 中的 Mybatis 依赖。当控制台显示 Tomcat 在 8080 端口启动且项目启动时间等信息时,表明项目创建成功。
- MySQL 数据库配置
- 可通过导入 example.sql 文件,或手动新建数据库及用户表(包含 name、pwd、userimg 等字段)来准备数据库。
- Spring Boot 2.0 以后默认使用 Hikari 连接池,在 application.properties 中需配置数据源信息,包括驱动类、数据库 URL(高版本 MySQL 需设置时区参数)、用户名、密码及连接池相关参数(如最小空闲连接数、最大连接数等)。配置完成后,可恢复之前屏蔽的 Mybatis 依赖。
- Spring Boot 分层架构回顾
- pojo 层:定义与数据库对应的属性,提供 get/set 方法、构造方法等。
- dao 层:通过接口访问数据库,具体实现写在 mapper.xml 中。
- service 层:调用 dao 层接口,先设计接口再实现,完成业务逻辑。
- controller 层:负责前后端交互,接收前端请求并调用 service 层,返回响应数据。
- MyBatis 逆向工程
- 在 pom.xml 中配置 mybatis-generator 插件及 MySQL 驱动依赖,指定 generatorConfig.xml 文件位置。
- 在 generatorConfig.xml 中配置 pojo 类、mapper.xml 映射文件、持久层接口的生成路径,以及数据库连接信息和表名。执行插件后自动生成相关文件,需注意避免反复执行导致 sql 语句重复报错。
- 整合测试项目
- 创建 service 和 controller 文件,在 application.properties 中配置 mybatis mapper 文件路径。
- 在启动类中添加 @MapperScan 注解扫描 dao 层包,在 dao 接口和 mapper.xml 中定义并实现查询方法,service 层实现接口调用 dao 层,controller 层通过 service 层处理请求。启动项目后,通过访问指定 URL(如http://localhost:8081/admin/find)测试功能。
2.登录、MD5 加密及拦截器:
Spring Boot 项目中登录功能实现、MD5 加密及拦截器配置,具体内容如下:
- 热部署配置
- 在
application.properties中添加配置spring.thymeleaf.cache=false,实现修改 HTML 页面后无需重启项目,刷新即可生效。 - 同时需在 IDEA 设置中开启相关编译选项,确保热部署功能正常使用。
- 在
- 前端 UI 框架与页面结构
- 采用 LayUI 作为前端框架,在
resources/static目录下组织 CSS、JS、图片等静态资源,登录页面和后台主页分别为login.html和index.html,存放于templates/admin目录。
- 采用 LayUI 作为前端框架,在
- Controller 层处理登录逻辑
- 通过
@GetMapping映射/userlogin、/等路径,返回登录页面;映射/sys_index返回后台主页。 @PostMapping("/userlogin")接收前端提交的用户名和密码,校验非空后调用auserService.login()方法,并根据返回结果跳转页面或提示错误。
- 通过
- Dao 层与 Service 层实现登录验证
- Dao 层:在
AuserMapper.java中定义login方法,接收用户名和密码参数;AuserMapper.xml中编写 SQL 语句,根据用户名和密码查询用户信息。 - Service 层:
AuserService.java定义userlogin接口,AuserServiceImpl.java实现时对密码进行 MD5 加密(调用MD5Util.MD5Encode),再调用 Dao 层方法查询用户。
- Dao 层:在
- 拦截器实现登录状态校验
- 拦截器类:
AdminLoginInterceptor实现HandlerInterceptor,在preHandle方法中检查请求路径是否以/admin开头且 session 中无用户信息,若未登录则重定向到登录页面并提示错误。 - 配置类:
MyWebMvcConfigurer通过@Configuration标记,注册拦截器并指定拦截路径(/admin/**),排除登录接口/admin/userlogin,确保未登录用户无法访问后台页面。
- 拦截器类:
3.退出功能、验证码登录及用户信息修改:
Spring Boot 项目中退出功能、验证码登录及用户信息(含密码)修改的实现,具体内容如下:
- 退出系统实现
- 在
AuserController中通过@GetMapping("/logout")映射退出路径,调用session.invalidate()销毁会话,并重定向到登录页面。
- 在
- 验证码登录功能
- 依赖配置:引入 Hutool 工具库的验证码模块
hutool-captcha(版本 5.8.7),用于生成和验证图片验证码。 - 验证码生成:创建
VerifyCodeController,通过CaptchaUtil.createShearCaptcha生成验证码图片,将验证码存入 Session 并输出图片流,响应头设置禁止缓存。 - 前端集成:在
login.html中添加验证码输入框和图片组件,点击图片可刷新验证码,引入 LayUI 组件进行表单验证。 - 后端验证:修改登录接口
@PostMapping("/userlogin"),增加验证码参数校验,从 Session 中获取验证码并调用verify方法验证,验证失败则返回错误提示。
- 依赖配置:引入 Hutool 工具库的验证码模块
- 用户信息修改
- 基础信息展示:在用户登录成功后,将用户名、密码、头像地址存入 Session,
index.html通过th:src获取头像地址并显示,默认头像存放在static/images/user.jpg,数据库auser表userimg字段默认值设为该路径。 - 密码修改逻辑:
- 旧密码验证:通过
@GetMapping("/password")接口接收旧密码,从 Session 获取系统存储的 MD5 密码,加密输入的旧密码后进行比对,返回验证结果。 - 信息更新:Service 层定义
updateUser方法,调用 MyBatis 自动生成的updateByPrimaryKeySelective接口更新用户信息;Controller 层接收新密码,加密后调用 Service 层方法完成更新。
- 旧密码验证:通过
- 页面跳转:通过
@GetMapping("/userInfo")映射用户信息编辑页面userInfo-edit.html,提供修改入口。
- 基础信息展示:在用户登录成功后,将用户名、密码、头像地址存入 Session,
4.修改头像:
Spring Boot 项目中修改头像的文件上传功能实现、静态资源配置、上传验证及部门管理增删改查示例,具体内容如下:
- 文件上传工具类
- 定义
UploadFileUtils.java,包含三个方法:getSuffixName获取文件后缀、getNewFileName生成 “当前时间 + 随机数 + 后缀” 的新文件名、getHost获取服务器主机名,用于处理文件上传的基础操作。
- 定义
- 文件上传逻辑实现
- 控制器处理:
AuserController的@PostMapping("/upload/userImg")接收文件,调用工具类生成新文件名,在本地或服务器创建upload文件夹,通过file.transferTo保存文件,并生成可访问的 URL(如http://localhost:8081/upload/xxx.jpg)存入数据库,同时更新 Session 中的头像地址。
- 控制器处理:
- 静态资源映射配置
- 在
MyWebMvcConfigurer中通过addResourceHandlers配置,将/upload/**路径映射到本地存储位置(file:upload/),确保前端可通过 URL 访问上传的图片资源。
- 在
- 上传功能验证与配置
- 打包运行:项目打包为 JAR 文件(如
example-1.0.jar)后,通过命令行java -jar运行,脱离 IDEA 验证图片上传和显示效果。 - 文件大小限制:在
application.properties中配置单个文件最大 10MB、总文件最大 30MB,避免大文件上传导致性能问题。
- 打包运行:项目打包为 JAR 文件(如
- 部门管理增删改查示例
- 数据库表:新建
department部门表,包含id、dname、dtel等字段,用于演示业务操作。 - 逆向工程:重新配置 Mybatis-generator,根据
department表自动生成对应的 pojo、dao、mapper.xml 文件,注意确保数据库中无同名表以免冲突。
- 数据库表:新建
5.分页查询:
Spring Boot 项目中基于 Layui 实现部门管理的分页查询功能,具体内容如下:
- 分页基础配置
- 前端与控制器:创建部门列表页面
department-list.html,通过DepartmentController的@GetMapping("/department")映射访问该页面。 - Layui 参数:Layui 表格默认请求
page(当前页)和limit(每页记录数)参数,点击分页按钮时以 GET 方式传递这两个参数。
- 前端与控制器:创建部门列表页面
- SQL 分页逻辑
- 查询语句:使用
LIMIT实现分页,公式为LIMIT limit*(page-1), limit,例如查询从第 3 条开始的 10 条记录为LIMIT 2, 10。
- 查询语句:使用
- 后端处理流程
- 控制器:
@GetMapping("/department/listall")接收包含page和limit的参数 Map,计算起始索引start=(page-1)*limit,调用 Service 层方法处理分页请求。 - 返回格式:遵循 Layui 表格的异步返回格式,定义
Result类包含code(状态码)、msg(提示信息)、count(总记录数)、data(当前页数据)。
- 控制器:
- Mapper 与 Service 层实现
- Mapper 接口:
findDepartmentList方法执行分页查询,getTotalDepartments方法统计总记录数。 - Mapper XML:编写 SQL 语句,
findDepartmentList使用LIMIT #{start},#{limit}分页,getTotalDepartments使用COUNT(*)统计总数。 - Service 实现:
getDepartmentsList方法调用 Mapper 获取分页数据和总记录数,组装成Result对象返回,满足 Layui 表格的数据格式要求。
- Mapper 接口:
- 时间格式处理
- 在实体类
Department.java的时间字段establishmentdate上添加@JsonFormat注解,设置格式为yyyy-MM-dd HH:mm:ss,时区为GMT+8,确保前端正确显示时间格式。
- 在实体类
6.模糊查询:
Spring Boot 项目中基于部门名称的模糊查询功能实现,结合分页逻辑与 SQL 注入安全说明,具体内容如下:
- Mapper 层 SQL 配置
- 模糊查询语句:在
DepartmentMapper.xml中定义findDepartmentListByName方法,使用like '%${dname}%'实现部门名称(dname)的模糊查询,按创建时间倒序排列并添加分页参数limit #{start},#{limit};同时定义getTotalDepartmentsByName方法统计符合条件的总记录数。 - SQL 注入风险:对比
${}与#{}的安全性,${}直接拼接参数易导致 SQL 注入(如用户输入恶意字符),而#{}通过预编译防止攻击,但此处因模糊查询需动态拼接百分号,故使用${}并强调其安全风险。
- 模糊查询语句:在
- 接口与方法定义
- Mapper 接口:
DepartmentMapper.java中声明findDepartmentListByName(接收 dname、start、limit 参数)和getTotalDepartmentsByName(接收 dname 参数)方法。 - Service 层:
DepartmentService.java定义getDepartmentsListByName接口,DepartmentServiceImpl.java实现时调用 Mapper 获取模糊查询结果和总记录数,组装成 Layui 表格所需的Result对象格式。
- Mapper 接口:
- 控制器处理
DepartmentController.java的listByName方法通过@GetMapping("/department/listbyname")接收包含page、limit(分页参数)和dname(查询关键词)的参数 Map,计算起始索引后调用 Service 层方法处理请求并返回结果。
7.添加:
Spring Boot 项目中部门管理模块的添加功能实现,包括刷新页面校验、唯一性约束设置、各层代码实现及参数接收方式,具体内容如下:
- 刷新页面校验
- 在
AuserController中通过@GetMapping("/reload")定义刷新接口,检查 Session 中是否存在用户名name,存在则返回true,用于验证用户登录状态。
- 在
- 唯一性约束设置
- 为避免部门名称重复,对数据库
department表的dname字段添加唯一性索引(UNIQUE),确保数据完整性。
- 为避免部门名称重复,对数据库
- 添加功能各层实现
- 控制器层:
@GetMapping("/department/add")跳转至部门添加页面department-add.html。@PostMapping("/department/add")支持三种参数接收方式:通过@RequestParam逐个获取参数、接收Map键值对、使用@RequestBody接收 JSON 格式数据(需前端调整提交格式为 JSON)。
- 服务层:
DepartmentService定义addDepartment接口,实现类中调用DepartmentMapper的insertSelective方法插入数据,根据插入结果返回操作成功或失败的Result对象。 - 持久层:利用 MyBatis 逆向工程生成的
insertSelective方法,支持选择性插入部门数据(非空字段才插入)。
- 控制器层:
- 前端参数提交调整
- 当使用
@RequestBody接收 JSON 数据时,前端页面需将表单数据通过JSON.stringify转换为 JSON 格式,并设置请求头contentType为application/json。
- 当使用
8.删除和修改:
Spring Boot 项目中部门管理模块的删除和修改功能实现,具体内容如下:
- 删除功能实现
- 持久层(Mapper):使用 MyBatis 逆向工程生成的
deleteByPrimaryKey方法,修改返回类型为boolean,通过主键 ID 删除部门记录。 - 服务层(Service):
DepartmentService定义deleteById接口,实现类中调用deleteByPrimaryKey,根据删除结果返回包含状态码和提示信息的Result对象。 - 控制器层(Controller):
@PostMapping("/department/delete")接收前端传递的部门 ID,调用服务层删除方法并返回结果。
- 持久层(Mapper):使用 MyBatis 逆向工程生成的
- 修改功能实现
- 显示待修改部门信息:
- 控制器:
@GetMapping("/department/edit")通过 ID 获取部门信息,若 ID 存在则将数据存入Model,传递到编辑页面department-edit.html。 - 服务层:
getDepartmentById方法调用 MyBatis 的selectByPrimaryKey,根据 ID 查询部门详情。
- 控制器:
- 提交修改信息:
- 持久层:使用
updateByPrimaryKeySelective方法,支持选择性更新部门字段(仅更新非空属性)。 - 服务层:
saveDepartment接口接收修改后的部门对象,调用updateByPrimaryKeySelective并返回操作结果。 - 控制器层:
@PostMapping("/department/edit")接收前端参数,更新部门对象的名称、电话、描述等信息,调用服务层完成修改。
- 持久层:使用
- 显示待修改部门信息:
以上功能通过各层协作,实现了基于主键的部门删除和动态字段修改,确保数据操作的准确性和完整性。
9.岗位管理:
Spring Boot 项目中岗位管理模块的增删改查功能实现,基于 MyBatis 逆向工程生成基础代码,结合分页、模糊查询等逻辑,具体内容如下:
1. 数据库表与逆向工程
- 岗位表结构:新建
post表,包含id(主键)、pname(岗位名称)、ptype(岗位类型)、organization(所属机构)等字段,其中pname设置唯一性约束避免重复。 - 逆向工程配置:重新配置 MyBatis-Generator,自动生成
post表对应的pojo、dao、mapper.xml文件,简化基础代码开发。
2. 分页查询
- 前端与控制器:创建岗位列表页面
post-list.html,PostController通过@GetMapping("/post")跳转页面,@GetMapping("/post/listall")接收page(当前页)和limit(每页记录数)参数,计算起始索引start=(page-1)*limit,调用 Service 层处理分页逻辑。 - Mapper 与 Service:
PostMapper定义findPostList(分页查询)和getTotalPosts(统计总数)方法,XML 中使用LIMIT #{start},#{limit}和COUNT(*)实现分页和计数;Service 层组装符合 Layui 表格格式的Result对象(包含code、msg、count、data)返回前端。
3. 模糊查询
- 按岗位名称查询:
PostMapper.xml中使用like '%${pname}%'实现模糊查询,PostMapper声明findPostListByName和getTotalPostsByName方法;Service 层和 Controller 层接收查询关键词pname,结合分页参数完成模糊查询并返回结果。
4. 删除功能
- 主键删除:利用 MyBatis 生成的
deleteByPrimaryKey方法,通过主键id删除岗位记录;Service 层封装删除结果为Result对象,Controller 层接收id参数并调用 Service 层方法执行删除。
5. 新增功能
- 唯一性校验:数据库对
pname字段添加唯一索引(UNIQUE),避免重复岗位名称。 - 数据插入:
PostController跳转添加页面post-add.html,接收前端参数创建Post对象,调用 Service 层addPost方法,通过insertSelective选择性插入非空字段数据。
6. 修改功能
- 显示待修改信息:
PostController通过@GetMapping("/post/edit")获取岗位id,调用 Service 层getPostById(基于selectByPrimaryKey)查询详情,存入Model传递到编辑页面post-edit.html。 - 提交修改:前端提交修改后,Controller 层更新
Post对象的pname、ptype等字段,调用 Service 层savePost方法,通过updateByPrimaryKeySelective选择性更新数据库记录。
核心逻辑总结
- 分层协作:各功能均遵循 “Controller 接收请求→Service 处理业务→Mapper 操作数据库” 的分层架构,利用 MyBatis 逆向工程生成的基础方法(如
selectByPrimaryKey、insertSelective)简化开发。 - 参数处理:分页、模糊查询、增删改操作均通过
@RequestParam或Map接收参数,确保前端与后端数据格式匹配,同时通过Result类统一返回格式,满足 Layui 组件的异步数据要求。
10.创建员工表后的岗位查询:
Spring Boot 项目中创建员工表后,如何通过关联查询实现岗位编制人数(员工数量)的统计与显示,具体内容如下:
- 数据库表结构与外键设置
- 员工表(staff):创建或导入
staff表,设置两个外键索引,depart_id关联department表的id(部门外键),post_id关联post表的id(岗位外键),通过外键约束确保数据一致性。 - 岗位表(post):
organization字段(编制人数)默认值为 0,需通过员工表中post_id相同的记录数重新赋值。
- 员工表(staff):创建或导入
- MyBatis 逆向工程与代码生成
- 重新配置 MyBatis-Generator,自动生成
staff表对应的pojo、dao、mapper.xml文件,为后续数据操作提供基础接口。
- 重新配置 MyBatis-Generator,自动生成
- 岗位编制人数统计逻辑
- 持久层(Mapper):在
StaffMapper.xml中定义getSamePostTotal方法,通过SELECT COUNT(*)统计staff表中特定post_id的员工数量;PostMapper使用updateByPrimaryKeySelective方法更新岗位表的organization字段。 - 服务层(Service):修改
PostServiceImpl的getPostsList方法,遍历岗位列表,调用staffMapper.getSamePostTotal(post.getId())获取每个岗位的员工数,存入post对象的organization属性,并更新岗位信息到数据库。
- 持久层(Mapper):在
- 数据关联与更新流程
- 通过岗位表与员工表的
post_id外键关联,实现 “岗位编制人数 = 该岗位员工总数” 的统计逻辑,确保岗位列表显示的编制人数实时反映员工表中的关联数据。
- 通过岗位表与员工表的
11.员工管理:
Spring Boot 项目中员工管理模块的实现,包括分页查询、详情查看、信息修改等功能,通过关联部门和岗位表实现数据整合与显示,具体内容如下:
1. 分页查询与数据关联
- 实体类扩展:在
Staff.java中添加departname(部门名)和postname(岗位名)属性(无数据库对应字段,仅用于前端显示),并提供get/set方法。 - 控制器与服务层:
StaffController通过@GetMapping("/staff/listall")接收分页参数page和limit,调用staffService.getStaffsList处理分页逻辑。StaffServiceImpl中,先通过staffMapper.findStaffList获取分页员工数据,再遍历每个员工,根据departId和postId查询对应的部门(departmentMapper.selectByPrimaryKey)和岗位(postMapper.selectByPrimaryKey)名称,设置到员工对象中,并根据enddate判断员工状态(“转正” 或 “试用期”)。
- 持久层:
StaffMapper.xml定义分页查询findStaffList和总数统计getTotalStaffs方法,使用LIMIT和COUNT(*)实现分页逻辑。
2. 详情页显示与时间格式处理
- 时间格式注解:在
Staff.java中对birthday、entrydate等时间字段添加@JsonFormat注解,指定格式为yyyy-MM-dd,时区为GMT+8,确保前端正确显示日期。 - 详情查询逻辑:
StaffController的staffView方法通过员工id查询员工信息,关联部门和岗位表获取名称,存入Model后跳转至详情页staff-view。
3. 员工信息修改功能
- 编辑页面数据准备:
StaffController的gotostaffEdit方法获取员工信息后,查询所有部门(departmentService.getDepartmentList)和岗位(postService.getPostsList),并准备性别、民族、学历等下拉列表数据,传递到编辑页面staff-edit。- 部门和岗位列表通过
DepartmentService和PostService的getDepartmentList、getPostsList方法获取,底层调用mapper的全量查询。
- 数据提交与更新:
- 前端以 JSON 格式提交修改数据,
StaffController通过@PostMapping("/staff/edit")接收参数,使用SimpleDateFormat解析日期字段(如birthday、entrydate),转换为java.sql.Date后更新员工对象。 StaffServiceImpl调用staffMapper.updateByPrimaryKeySelective实现选择性更新,返回操作结果。
- 前端以 JSON 格式提交修改数据,
核心逻辑与技术点
- 外键关联查询:通过员工表的
departId和postId外键,关联部门表和岗位表,实现 “员工 - 部门 - 岗位” 三级数据联动,确保前端显示完整信息。 - 状态动态判断:根据员工试用期结束日期
enddate与当前时间的对比,动态设置员工状态(“转正” 或 “试用期”),增强业务逻辑的自动化。 - 分层架构协作:遵循 “Controller(请求处理)→ Service(业务逻辑)→ Mapper(数据库操作)” 分层模式,利用 MyBatis 的
selectByPrimaryKey和updateByPrimaryKeySelective等方法简化数据操作。
通过以上实现,员工管理模块实现了数据的分页展示、详情查看、动态状态判断及复杂表单编辑,确保了前端与后端的数据一致性和操作便捷性。