1. 项目背景与意义随着高校毕业生人数逐年增加求职市场竞争日益激烈。传统的高校就业信息发布方式如公告栏、邮件群发存在信息分散、更新不及时、匹配效率低等问题。同时企业招聘方也面临难以精准触达目标院校和专业学生的困境。因此开发一个基于Spring Boot的高校求职招聘信息管理系统具有重要的现实意义对学生而言提供一个集中、实时、个性化的招聘信息平台方便快捷地获取与自身专业、意向匹配的岗位并能在线投递简历、查看进度。对企业而言能够高效地发布和管理招聘需求精准筛选符合条件的学生简历降低招聘成本提升人才引进效率。对高校就业指导中心而言实现招聘信息的数字化、流程化管理便于统计就业数据、分析就业趋势为就业指导工作提供数据支持。本系统旨在构建一个连接学生、企业和学校的三方平台利用现代Web技术提升求职招聘全流程的效率和体验。2. 技术栈选型系统采用前后端分离的架构模式后端基于Spring Boot框架构建具体技术栈如下2.1 后端技术核心框架Spring Boot 2.7.x安全框架Spring Security JWT (JSON Web Token)数据持久层Spring Data JPA (默认使用Hibernate实现)数据库MySQL 8.0缓存Redis (用于会话管理、热点数据缓存)API文档SpringDoc OpenAPI 3 (Swagger UI)构建工具Maven单元测试JUnit 5, Mockito2.2 前端技术建议框架Vue 3 或 React 18UI组件库Element Plus (Vue) 或 Ant Design (React)状态管理Pinia (Vue) 或 Redux Toolkit (React)HTTP客户端Axios构建工具Vite2.3 开发与部署版本控制Git容器化Docker, Docker Compose持续集成/部署Jenkins 或 GitLab CI3. 系统核心功能模块设计3.1 用户角色与权限学生用户注册/登录、完善个人简历、浏览/搜索/收藏职位、在线投递、查看投递进度、接收面试通知。企业用户注册/认证、发布/管理招聘职位、筛选/管理收到的简历、发送面试邀请、查看候选人信息。管理员学校就业中心管理所有用户、审核企业资质、管理全局招聘信息、统计分析就业数据、发布公告。3.2 核心功能模块用户认证与授权模块实现基于角色的登录、注册、JWT令牌签发与验证。个人信息与简历模块学生维护教育背景、技能、项目经历等企业维护公司信息。招聘信息管理模块企业发布职位职位名称、要求、薪资、地点等管理员审核学生浏览与搜索。简历投递与处理模块学生投递简历企业查看、筛选标记为“已读”、“感兴趣”、“不合适”等。消息通知模块系统站内信、邮件通知如投递成功、面试邀请、状态更新。数据统计与分析模块管理员后台查看职位发布量、投递量、热门行业/岗位等统计数据。4. 数据库核心表设计以下是几个核心实体及其主要字段的简要设计-- 用户表 (统一存储学生、企业、管理员) CREATE TABLE sys_user ( id bigint NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(255) NOT NULL COMMENT 加密后的密码, email varchar(100) NOT NULL COMMENT 邮箱, phone varchar(20) DEFAULT NULL COMMENT 手机号, avatar varchar(500) DEFAULT NULL COMMENT 头像URL, user_type tinyint NOT NULL COMMENT 用户类型1-学生2-企业3-管理员, status tinyint DEFAULT 1 COMMENT 状态0-禁用1-正常, create_time datetime DEFAULT CURRENT_TIMESTAMP, update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY uk_username (username), UNIQUE KEY uk_email (email) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统用户表; -- 学生详细信息表 CREATE TABLE student_profile ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 关联用户ID, real_name varchar(50) DEFAULT NULL COMMENT 真实姓名, gender tinyint DEFAULT NULL COMMENT 性别, school varchar(100) DEFAULT NULL COMMENT 学校, major varchar(100) DEFAULT NULL COMMENT 专业, education varchar(20) DEFAULT NULL COMMENT 学历, graduation_year int DEFAULT NULL COMMENT 毕业年份, resume_url varchar(500) DEFAULT NULL COMMENT 简历文件URL, skills text COMMENT 技能标签JSON数组存储, PRIMARY KEY (id), UNIQUE KEY uk_user_id (user_id), CONSTRAINT fk_student_user FOREIGN KEY (user_id) REFERENCES sys_user (id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT学生详细信息表; -- 企业信息表 CREATE TABLE company ( id bigint NOT NULL AUTO_INCREMENT, user_id bigint NOT NULL COMMENT 关联用户ID, company_name varchar(200) NOT NULL COMMENT 公司名称, logo varchar(500) DEFAULT NULL COMMENT 公司Logo URL, industry varchar(100) DEFAULT NULL COMMENT 所属行业, scale varchar(50) DEFAULT NULL COMMENT 公司规模, address varchar(500) DEFAULT NULL COMMENT 公司地址, description text COMMENT 公司简介, verified tinyint DEFAULT 0 COMMENT 认证状态0-未认证1-已认证, PRIMARY KEY (id), UNIQUE KEY uk_user_id (user_id), CONSTRAINT fk_company_user FOREIGN KEY (user_id) REFERENCES sys_user (id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT企业信息表; -- 招聘职位表 CREATE TABLE job_position ( id bigint NOT NULL AUTO_INCREMENT, company_id bigint NOT NULL COMMENT 发布企业ID, title varchar(200) NOT NULL COMMENT 职位名称, description text NOT NULL COMMENT 职位描述, requirements text COMMENT 职位要求, salary_range varchar(100) DEFAULT NULL COMMENT 薪资范围, work_location varchar(200) DEFAULT NULL COMMENT 工作地点, job_type tinyint DEFAULT NULL COMMENT 职位类型1-全职2-实习, status tinyint DEFAULT 1 COMMENT 状态0-已下线1-招聘中, publish_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 发布时间, PRIMARY KEY (id), KEY idx_company_id (company_id), KEY idx_status_publish (status, publish_time), CONSTRAINT fk_job_company FOREIGN KEY (company_id) REFERENCES company (id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT招聘职位表; -- 简历投递记录表 CREATE TABLE job_application ( id bigint NOT NULL AUTO_INCREMENT, job_id bigint NOT NULL COMMENT 职位ID, student_id bigint NOT NULL COMMENT 投递学生ID, resume_url varchar(500) DEFAULT NULL COMMENT 投递时使用的简历URL, status tinyint DEFAULT 0 COMMENT 状态0-已投递1-已查看2-感兴趣3-通知面试4-不合适, apply_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT 投递时间, feedback text COMMENT 企业反馈, PRIMARY KEY (id), UNIQUE KEY uk_job_student (job_id, student_id), KEY idx_student_status (student_id, status), KEY idx_job_status (job_id, status), CONSTRAINT fk_application_job FOREIGN KEY (job_id) REFERENCES job_position (id) ON DELETE CASCADE, CONSTRAINT fk_application_student FOREIGN KEY (student_id) REFERENCES student_profile (id) ON DELETE CASCADE ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT职位申请记录表;5. 核心代码示例 (Spring Boot)5.1 实体类 (JobPosition.java)package com.example.careersystem.entity; import lombok.Data; import javax.persistence.*; import java.time.LocalDateTime; Entity Table(name job_position) Data public class JobPosition { Id GeneratedValue(strategy GenerationType.IDENTITY) private Long id; ManyToOne(fetch FetchType.LAZY) JoinColumn(name company_id, nullable false) private Company company; Column(nullable false, length 200) private String title; Column(nullable false, columnDefinition TEXT) private String description; Column(columnDefinition TEXT) private String requirements; Column(name salary_range, length 100) private String salaryRange; Column(name work_location, length 200) private String workLocation; Column(name job_type) private Integer jobType; // 1-全职2-实习 private Integer status 1; // 0-下线1-招聘中 Column(name publish_time) private LocalDateTime publishTime LocalDateTime.now(); // 省略 getter/setter (由 Lombok Data 生成) }5.2 数据访问层 (JobPositionRepository.java)package com.example.careersystem.repository; import com.example.careersystem.entity.JobPosition; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.util.List; Repository public interface JobPositionRepository extends JpaRepositoryJobPosition, Long { // 根据企业ID分页查询职位 PageJobPosition findByCompanyId(Long companyId, Pageable pageable); // 根据状态查询职位 ListJobPosition findByStatus(Integer status); // 复杂查询示例根据关键词搜索职位 (标题或描述中包含) Query(SELECT jp FROM JobPosition jp WHERE jp.status 1 AND (LOWER(jp.title) LIKE LOWER(CONCAT(%, :keyword, %)) OR LOWER(jp.description) LIKE LOWER(CONCAT(%, :keyword, %)))) PageJobPosition searchByKeyword(Param(keyword) String keyword, Pageable pageable); // 统计某企业的职位数量 Long countByCompanyId(Long companyId); }5.3 服务层 (JobPositionService.java)package com.example.careersystem.service; import com.example.careersystem.entity.JobPosition; import com.example.careersystem.repository.JobPositionRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Optional; Service public class JobPositionService { Autowired private JobPositionRepository jobPositionRepository; // 发布新职位 Transactional public JobPosition createJobPosition(JobPosition jobPosition) { // 这里可以添加业务逻辑如权限校验、数据校验等 return jobPositionRepository.save(jobPosition); } // 分页查询所有招聘中的职位 public PageJobPosition getActivePositions(Pageable pageable) { return jobPositionRepository.findByStatus(1, pageable); } // 根据关键词搜索职位 public PageJobPosition searchPositions(String keyword, Pageable pageable) { if (keyword null || keyword.trim().isEmpty()) { return getActivePositions(pageable); } return jobPositionRepository.searchByKeyword(keyword.trim(), pageable); } // 根据ID获取职位详情 public OptionalJobPosition getPositionById(Long id) { return jobPositionRepository.findById(id); } // 更新职位信息 Transactional public JobPosition updateJobPosition(Long id, JobPosition updatedPosition) { return jobPositionRepository.findById(id).map(position - { position.setTitle(updatedPosition.getTitle()); position.setDescription(updatedPosition.getDescription()); position.setRequirements(updatedPosition.getRequirements()); position.setSalaryRange(updatedPosition.getSalaryRange()); position.setWorkLocation(updatedPosition.getWorkLocation()); position.setJobType(updatedPosition.getJobType()); // 注意status 和 publishTime 通常有单独的接口控制 return jobPositionRepository.save(position); }).orElseThrow(() - new RuntimeException(职位不存在ID: id)); } // 下线职位逻辑删除 Transactional public void deactivatePosition(Long id) { jobPositionRepository.findById(id).ifPresent(position - { position.setStatus(0); jobPositionRepository.save(position); }); } }5.4 控制层 (JobPositionController.java)package com.example.careersystem.controller; import com.example.careersystem.entity.JobPosition; import com.example.careersystem.service.JobPositionService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; RestController RequestMapping(/api/positions) Tag(name 招聘职位管理, description 招聘职位的增删改查与搜索接口) public class JobPositionController { Autowired private JobPositionService jobPositionService; PostMapping Operation(summary 发布新职位, description 企业用户发布一个新的招聘职位) public ResponseEntityJobPosition createPosition(Valid RequestBody JobPosition jobPosition) { JobPosition created jobPositionService.createJobPosition(jobPosition); return ResponseEntity.ok(created); } GetMapping Operation(summary 分页获取招聘中的职位, description 获取所有状态为“招聘中”的职位列表) public ResponseEntityPageJobPosition getActivePositions( PageableDefault(size 10, sort publishTime,desc) Pageable pageable) { PageJobPosition positions jobPositionService.getActivePositions(pageable); return ResponseEntity.ok(positions); } GetMapping(/search) Operation(summary 搜索职位, description 根据关键词搜索职位标题或描述) public ResponseEntityPageJobPosition searchPositions( RequestParam(required false) String keyword, PageableDefault(size 10) Pageable pageable) { PageJobPosition positions jobPositionService.searchPositions(keyword, pageable); return ResponseEntity.ok(positions); } GetMapping(/{id}) Operation(summary 获取职位详情, description 根据ID获取职位详细信息) public ResponseEntityJobPosition getPositionById(PathVariable Long id) { return jobPositionService.getPositionById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } PutMapping(/{id}) Operation(summary 更新职位信息, description 更新指定ID的职位信息) public ResponseEntityJobPosition updatePosition(PathVariable Long id, Valid RequestBody JobPosition updatedPosition) { JobPosition po