人事管理系统总结
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
等方法简化数据操作。
通过以上实现,员工管理模块实现了数据的分页展示、详情查看、动态状态判断及复杂表单编辑,确保了前端与后端的数据一致性和操作便捷性。