当前位置: 首页 > news >正文

Java全栈项目 - 校园招聘信息平台

项目介绍

校园招聘信息平台是一个面向高校学生和企业的双向服务平台。该系统帮助企业发布招聘信息,方便学生查询职位并投递简历,同时为学校就业部门提供就业数据分析功能。

技术栈

后端

  • Spring Boot 2.x
  • Spring Security
  • MyBatis Plus
  • MySQL 8.0
  • Redis
  • RabbitMQ

前端

  • Vue.js 2.x
  • Element UI
  • Axios
  • Echarts

核心功能

1. 用户模块

  • 学生注册/登录
  • 企业注册/登录
  • 管理员登录
  • 基于JWT的认证授权

2. 企业模块

  • 企业信息管理
  • 职位发布/管理
  • 简历筛选
  • 面试安排

3. 学生模块

  • 个人信息维护
  • 简历制作
  • 职位搜索/投递
  • 投递状态跟踪

4. 数据分析模块

  • 就业率统计
  • 薪资分布分析
  • 行业/地区分布
  • 就业趋势分析

系统架构

├── recruitment-system
│   ├── recruitment-common    -- 公共模块
│   ├── recruitment-admin     -- 管理后台
│   ├── recruitment-api       -- 接口服务
│   ├── recruitment-service   -- 业务逻辑
│   ├── recruitment-dao       -- 数据访问
│   └── recruitment-web       -- 前端页面

数据库设计

主要包含以下核心表:

-- 用户表
CREATE TABLE user (id BIGINT PRIMARY KEY,username VARCHAR(50),password VARCHAR(100),role VARCHAR(20),create_time DATETIME
);-- 企业表
CREATE TABLE company (id BIGINT PRIMARY KEY,name VARCHAR(100),industry VARCHAR(50),scale VARCHAR(50),description TEXT
);-- 职位表
CREATE TABLE position (id BIGINT PRIMARY KEY,company_id BIGINT,title VARCHAR(100),salary VARCHAR(50),education VARCHAR(20),description TEXT
);-- 简历表
CREATE TABLE resume (id BIGINT PRIMARY KEY,student_id BIGINT,education TEXT,experience TEXT,skills TEXT
);

项目亮点

1. 分布式Session

使用Redis实现分布式Session,支持集群部署

2. 消息队列

使用RabbitMQ处理异步任务:

  • 简历投递通知
  • 面试通知
  • 系统消息推送

3. 全文检索

整合Elasticsearch实现职位搜索功能:

  • 多条件组合查询
  • 结果高亮显示
  • 智能推荐

4. 性能优化

  • Redis缓存热点数据
  • MyBatis SQL优化
  • 前端资源压缩
  • 图片CDN加速

项目总结

通过这个项目的开发,不仅巩固了Java全栈技术,还学习了:

  1. 大型项目的架构设计
  2. 分布式系统开发经验
  3. 性能优化最佳实践
  4. 项目开发完整流程

后续优化方向

  1. 引入Spring Cloud实现微服务架构
  2. 添加大数据分析功能
  3. 开发移动端应用
  4. 优化系统性能和用户体验

Java全栈项目 - 校园招聘信息平台(一):用户模块与企业模块详解

一、用户模块详细设计

1. 数据库设计

-- 用户基础信息表
CREATE TABLE sys_user (id BIGINT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL COMMENT '用户名',password VARCHAR(100) NOT NULL COMMENT '密码',role VARCHAR(20) NOT NULL COMMENT '角色:STUDENT/COMPANY/ADMIN',email VARCHAR(100) COMMENT '邮箱',phone VARCHAR(20) COMMENT '手机号',status TINYINT DEFAULT 1 COMMENT '状态:0禁用,1启用',create_time DATETIME DEFAULT CURRENT_TIMESTAMP,update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);-- 学生信息表
CREATE TABLE student_info (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL COMMENT '关联用户ID',real_name VARCHAR(50) COMMENT '真实姓名',gender TINYINT COMMENT '性别:0女,1男',birthday DATE COMMENT '出生日期',school VARCHAR(100) COMMENT '学校',major VARCHAR(100) COMMENT '专业',education VARCHAR(20) COMMENT '学历',graduation_year INT COMMENT '毕业年份'
);-- 企业信息表
CREATE TABLE company_info (id BIGINT PRIMARY KEY AUTO_INCREMENT,user_id BIGINT NOT NULL COMMENT '关联用户ID',company_name VARCHAR(100) NOT NULL COMMENT '企业名称',industry VARCHAR(50) COMMENT '所属行业',scale VARCHAR(50) COMMENT '企业规模',location VARCHAR(200) COMMENT '企业地址',website VARCHAR(200) COMMENT '企业官网',license_no VARCHAR(100) COMMENT '营业执照号',description TEXT COMMENT '企业简介',verify_status TINYINT DEFAULT 0 COMMENT '认证状态:0未认证,1已认证'
);

2. 核心功能实现

2.1 注册功能
@Service
public class UserServiceImpl implements UserService {@Autowiredprivate PasswordEncoder passwordEncoder;@Transactionalpublic void registerStudent(StudentRegisterDTO dto) {// 1. 参数校验validateRegisterParams(dto);// 2. 检查用户名是否存在checkUsernameExist(dto.getUsername());// 3. 保存用户基本信息SysUser user = new SysUser();user.setUsername(dto.getUsername());user.setPassword(passwordEncoder.encode(dto.getPassword()));user.setRole("STUDENT");userMapper.insert(user);// 4. 保存学生详细信息StudentInfo studentInfo = new StudentInfo();BeanUtils.copyProperties(dto, studentInfo);studentInfo.setUserId(user.getId());studentInfoMapper.insert(studentInfo);// 5. 发送注册成功邮件sendRegisterEmail(dto.getEmail());}@Transactionalpublic void registerCompany(CompanyRegisterDTO dto) {// 类似学生注册流程// 额外增加企业认证材料上传// ...}
}
2.2 登录认证
@Service
public class AuthServiceImpl implements AuthService {@Autowiredprivate JwtTokenProvider tokenProvider;public LoginVO login(LoginDTO dto) {// 1. 认证用户Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(dto.getUsername(), dto.getPassword()));// 2. 生成JWT TokenString token = tokenProvider.generateToken(authentication);// 3. 获取用户信息UserDetails userDetails = (UserDetails) authentication.getPrincipal();// 4. 返回登录信息return LoginVO.builder().token(token).userInfo(buildUserInfo(userDetails)).build();}
}
2.3 JWT认证授权
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {try {String jwt = getJwtFromRequest(request);if (StringUtils.hasText(jwt) && tokenProvider.validateToken(jwt)) {Long userId = tokenProvider.getUserIdFromJWT(jwt);UserDetails userDetails = userService.loadUserById(userId);UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authentication);}} catch (Exception ex) {logger.error("JWT认证失败", ex);}chain.doFilter(request, response);}
}

二、企业模块详细设计

1. 数据库设计

-- 职位表
CREATE TABLE position (id BIGINT PRIMARY KEY AUTO_INCREMENT,company_id BIGINT NOT NULL COMMENT '企业ID',title VARCHAR(100) NOT NULL COMMENT '职位名称',department VARCHAR(50) COMMENT '所属部门',salary_min INT COMMENT '最低薪资',salary_max INT COMMENT '最高薪资',education VARCHAR(20) COMMENT '学历要求',experience VARCHAR(50) COMMENT '经验要求',description TEXT COMMENT '职位描述',requirement TEXT COMMENT '任职要求',status TINYINT DEFAULT 1 COMMENT '状态:0下线,1上线',create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);-- 简历投递表
CREATE TABLE resume_delivery (id BIGINT PRIMARY KEY AUTO_INCREMENT,position_id BIGINT NOT NULL COMMENT '职位ID',student_id BIGINT NOT NULL COMMENT '学生ID',resume_id BIGINT NOT NULL COMMENT '简历ID',status VARCHAR(20) DEFAULT 'PENDING' COMMENT '状态:PENDING/PASSED/REJECTED',hr_notes TEXT COMMENT 'HR备注',create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);-- 面试安排表
CREATE TABLE interview (id BIGINT PRIMARY KEY AUTO_INCREMENT,delivery_id BIGINT NOT NULL COMMENT '投递ID',interview_time DATETIME NOT NULL COMMENT '面试时间',location VARCHAR(200) COMMENT '面试地点',type VARCHAR(20) COMMENT '面试方式:ONLINE/OFFLINE',round INT COMMENT '面试轮次',status VARCHAR(20) COMMENT '状态:PENDING/COMPLETED/CANCELED',feedback TEXT COMMENT '面试反馈',create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

2. 核心功能实现

2.1 企业信息管理
@Service
public class CompanyServiceImpl implements CompanyService {@Transactionalpublic void updateCompanyInfo(CompanyUpdateDTO dto) {// 1. 验证操作权限checkCompanyPermission(dto.getCompanyId());// 2. 更新基本信息CompanyInfo companyInfo = new CompanyInfo();BeanUtils.copyProperties(dto, companyInfo);companyInfoMapper.updateById(companyInfo);// 3. 处理企业Logo上传if (dto.getLogoFile() != null) {String logoUrl = fileService.uploadImage(dto.getLogoFile());companyInfoMapper.updateLogo(dto.getCompanyId(), logoUrl);}}public CompanyDetailVO getCompanyDetail(Long companyId) {// 1. 获取企业基本信息CompanyInfo info = companyInfoMapper.selectById(companyId);// 2. 获取在招职位数Integer positionCount = positionMapper.countByCompanyId(companyId);// 3. 构建返回数据return CompanyDetailVO.builder().basicInfo(info).positionCount(positionCount).build();}
}
2.2 职位管理
@Service
public class PositionServiceImpl implements PositionService {@Transactionalpublic void publishPosition(PositionPublishDTO dto) {// 1. 验证企业权限checkCompanyPermission(dto.getCompanyId());// 2. 保存职位信息Position position = new Position();BeanUtils.copyProperties(dto, position);positionMapper.insert(position);// 3. 发送职位消息到消息队列sendPositionMessage(position);// 4. 更新搜索索引updateSearchIndex(position);}public PageResult<PositionVO> queryPositions(PositionQueryDTO query) {// 1. 构建查询条件LambdaQueryWrapper<Position> wrapper = new QueryWrapper<Position>().lambda().eq(query.getCompanyId() != null, Position::getCompanyId, query.getCompanyId()).like(StringUtils.isNotBlank(query.getKeyword()), Position::getTitle, query.getKeyword()).eq(Position::getStatus, 1);// 2. 分页查询Page<Position> page = positionMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), wrapper);// 3. 转换返回结果return PageResult.build(page, this::convertToVO);}
}
2.3 简历筛选
@Service
public class ResumeDeliveryServiceImpl implements ResumeDeliveryService {public PageResult<DeliveryVO> queryDeliveryList(DeliveryQueryDTO query) {// 1. 分页查询投递记录Page<ResumeDelivery> page = deliveryMapper.queryDeliveryList(new Page<>(query.getPageNum(), query.getPageSize()),query);// 2. 批量查询简历信息List<Long> resumeIds = page.getRecords().stream().map(ResumeDelivery::getResumeId).collect(Collectors.toList());Map<Long, ResumeVO> resumeMap = resumeService.batchGetResumeVO(resumeIds);// 3. 构建返回数据return PageResult.build(page, delivery -> {DeliveryVO vo = new DeliveryVO();BeanUtils.copyProperties(delivery, vo);vo.setResume(resumeMap.get(delivery.getResumeId()));return vo;});}@Transactionalpublic void updateDeliveryStatus(DeliveryStatusDTO dto) {// 1. 更新投递状态ResumeDelivery delivery = new ResumeDelivery();delivery.setId(dto.getDeliveryId());delivery.setStatus(dto.getStatus());delivery.setHrNotes(dto.getNotes());deliveryMapper.updateById(delivery);// 2. 发送状态变更通知messageService.sendDeliveryStatusMessage(dto);}
}
2.4 面试安排
@Service
public class InterviewServiceImpl implements InterviewService {@Transactionalpublic void arrangeInterview(InterviewArrangeDTO dto) {// 1. 创建面试记录Interview interview = new Interview();BeanUtils.copyProperties(dto, interview);interviewMapper.insert(interview);// 2. 更新投递状态deliveryService.updateStatus(dto.getDeliveryId(), "INTERVIEWING");// 3. 发送面试通知ResumeDelivery delivery = deliveryMapper.selectById(dto.getDeliveryId());sendInterviewNotification(delivery, interview);}private void sendInterviewNotification(ResumeDelivery delivery, Interview interview) {// 1. 发送邮件通知EmailMessage emailMessage = buildInterviewEmailMessage(delivery, interview);messageService.sendEmail(emailMessage);// 2. 发送短信通知SmsMessage smsMessage = buildInterviewSmsMessage(delivery, interview);messageService.sendSms(smsMessage);// 3. 发送系统站内信SystemMessage systemMessage = buildInterviewSystemMessage(delivery, interview);messageService.sendSystemMessage(systemMessage);}
}

3. 接口文档示例

/api/company/info:put:summary: 更新企业信息parameters:- name: dtoin: bodyrequired: trueschema:type: objectproperties:companyId:type: integerdescription: 企业IDcompanyName:type: stringdescription: 企业名称industry:type: stringdescription: 所属行业responses:200:description: 更新成功/api/position/publish:post:summary: 发布职位parameters:- name: dtoin: bodyrequired: trueschema:type: objectproperties:companyId:type: integertitle:type: stringsalary:type: stringresponses:200:description: 发布成功

以上是用户模块和企业模块的详细设计。包含了:

  1. 完整的数据库表设计
  2. 核心业务逻辑实现
  3. 关键功能的代码示例
  4. 接口文档规范

这些模块的实现考虑了:

  • 数据安全性(密码加密、JWT认证)
  • 业务完整性(事务管理)
  • 异步处理(消息队列)
  • 通知提醒(邮件、短信、站内信)

Java全栈项目 - 校园招聘信息平台(二):学生模块与数据分析模块详解

一、学生模块详细设计

1. 数据库设计

-- 简历表
CREATE TABLE resume (id BIGINT PRIMARY KEY AUTO_INCREMENT,student_id BIGINT NOT NULL COMMENT '学生ID',title VARCHAR(100) COMMENT '简历标题',avatar_url VARCHAR(200) COMMENT '头像URL',expect_salary VARCHAR(50) COMMENT '期望薪资',expect_city VARCHAR(50) COMMENT '期望城市',expect_position VARCHAR(100) COMMENT '期望职位',self_evaluation TEXT COMMENT '自我评价',create_time DATETIME DEFAULT CURRENT_TIMESTAMP,update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);-- 教育经历表
CREATE TABLE resume_education (id BIGINT PRIMARY KEY AUTO_INCREMENT,resume_id BIGINT NOT NULL COMMENT '简历ID',school VARCHAR(100) NOT NULL COMMENT '学校名称',major VARCHAR(100) COMMENT '专业',degree VARCHAR(50) COMMENT '学历',start_date DATE COMMENT '开始时间',end_date DATE COMMENT '结束时间',gpa VARCHAR(20) COMMENT '学分绩点',description TEXT COMMENT '在校经历'
);-- 项目经历表
CREATE TABLE resume_project (id BIGINT PRIMARY KEY AUTO_INCREMENT,resume_id BIGINT NOT NULL,name VARCHAR(100) NOT NULL COMMENT '项目名称',role VARCHAR(50) COMMENT '担任角色',start_date DATE COMMENT '开始时间',end_date DATE COMMENT '结束时间',description TEXT COMMENT '项目描述',achievement TEXT COMMENT '项目成就'
);-- 求职进度表
CREATE TABLE job_progress (id BIGINT PRIMARY KEY AUTO_INCREMENT,student_id BIGINT NOT NULL,position_id BIGINT NOT NULL,company_id BIGINT NOT NULL,status VARCHAR(20) COMMENT '状态:待处理/已查看/面试/通过/拒绝',latest_time DATETIME COMMENT '最新进展时间',create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);

2. 核心功能实现

2.1 简历管理
@Service
public class ResumeServiceImpl implements ResumeService {@Transactionalpublic Long createResume(ResumeCreateDTO dto) {// 1. 保存基本信息Resume resume = new Resume();BeanUtils.copyProperties(dto, resume);resumeMapper.insert(resume);// 2. 保存教育经历saveEducationList(resume.getId(), dto.getEducationList());// 3. 保存项目经历saveProjectList(resume.getId(), dto.getProjectList());// 4. 处理头像上传if (dto.getAvatarFile() != null) {String avatarUrl = fileService.uploadImage(dto.getAvatarFile());resumeMapper.updateAvatar(resume.getId(), avatarUrl);}return resume.getId();}public ResumeDetailVO getResumeDetail(Long resumeId) {// 1. 获取基本信息Resume resume = resumeMapper.selectById(resumeId);// 2. 获取教育经历List<ResumeEducation> educationList = educationMapper.selectByResumeId(resumeId);// 3. 获取项目经历List<ResumeProject> projectList = projectMapper.selectByResumeId(resumeId);// 4. 构建返回数据return ResumeDetailVO.builder().basicInfo(resume).educationList(educationList).projectList(projectList).build();}
}
2.2 职位搜索
@Service
public class PositionSearchServiceImpl implements PositionSearchService {@Autowiredprivate ElasticsearchRestTemplate esTemplate;public PageResult<PositionVO> searchPositions(PositionSearchDTO dto) {// 1. 构建搜索条件BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();// 关键词搜索if (StringUtils.isNotBlank(dto.getKeyword())) {boolQuery.must(QueryBuilders.multiMatchQuery(dto.getKeyword()).field("title", 3.0f).field("description").field("requirement"));}// 城市筛选if (StringUtils.isNotBlank(dto.getCity())) {boolQuery.filter(QueryBuilders.termQuery("city", dto.getCity()));}// 薪资范围if (dto.getSalaryMin() != null && dto.getSalaryMax() != null) {boolQuery.filter(QueryBuilders.rangeQuery("salaryMin").gte(dto.getSalaryMin()).lte(dto.getSalaryMax()));}// 2. 执行搜索NativeSearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(boolQuery).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(dto.getPageNum(), dto.getPageSize())).build();SearchHits<PositionES> searchHits = esTemplate.search(searchQuery, PositionES.class);// 3. 处理高亮显示return PageResult.build(searchHits, this::convertToVO);}
}
2.3 职位投递
@Service
public class JobApplicationServiceImpl implements JobApplicationService {@Transactionalpublic void applyPosition(JobApplyDTO dto) {// 1. 检查是否重复投递checkDuplicateApply(dto.getStudentId(), dto.getPositionId());// 2. 创建投递记录ResumeDelivery delivery = new ResumeDelivery();delivery.setStudentId(dto.getStudentId());delivery.setPositionId(dto.getPositionId());delivery.setResumeId(dto.getResumeId());delivery.setStatus("PENDING");deliveryMapper.insert(delivery);// 3. 创建求职进度JobProgress progress = new JobProgress();progress.setStudentId(dto.getStudentId());progress.setPositionId(dto.getPositionId());progress.setCompanyId(dto.getCompanyId());progress.setStatus("待处理");progressMapper.insert(progress);// 4. 发送投递通知sendDeliveryNotification(delivery);}public List<JobProgressVO> getProgressList(Long studentId) {// 1. 查询进度列表List<JobProgress> progressList = progressMapper.selectByStudentId(studentId);// 2. 批量查询职位和公司信息Set<Long> positionIds = progressList.stream().map(JobProgress::getPositionId).collect(Collectors.toSet());Map<Long, PositionVO> positionMap = positionService.batchGetPositionVO(positionIds);// 3. 构建返回数据return progressList.stream().map(progress -> {JobProgressVO vo = new JobProgressVO();BeanUtils.copyProperties(progress, vo);vo.setPosition(positionMap.get(progress.getPositionId()));return vo;}).collect(Collectors.toList());}
}

二、数据分析模块详细设计

1. 数据库设计

-- 就业统计表
CREATE TABLE employment_stats (id BIGINT PRIMARY KEY AUTO_INCREMENT,year INT NOT NULL COMMENT '统计年份',month INT NOT NULL COMMENT '统计月份',school_id BIGINT COMMENT '学校ID',major_id BIGINT COMMENT '专业ID',total_students INT COMMENT '毕业生总数',employed_count INT COMMENT '已就业人数',employment_rate DECIMAL(5,2) COMMENT '就业率',avg_salary DECIMAL(10,2) COMMENT '平均薪资',create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);-- 行业分布表
CREATE TABLE industry_distribution (id BIGINT PRIMARY KEY AUTO_INCREMENT,year INT NOT NULL,industry VARCHAR(50) NOT NULL COMMENT '行业',student_count INT COMMENT '就业人数',salary_avg DECIMAL(10,2) COMMENT '平均薪资',proportion DECIMAL(5,2) COMMENT '占比'
);-- 地区分布表
CREATE TABLE region_distribution (id BIGINT PRIMARY KEY AUTO_INCREMENT,year INT NOT NULL,province VARCHAR(50) NOT NULL COMMENT '省份',city VARCHAR(50) NOT NULL COMMENT '城市',student_count INT COMMENT '就业人数',salary_avg DECIMAL(10,2) COMMENT '平均薪资',proportion DECIMAL(5,2) COMMENT '占比'
);

2. 核心功能实现

2.1 就业率统计
@Service
public class EmploymentStatsServiceImpl implements EmploymentStatsService {public EmploymentOverviewVO calculateEmploymentStats(StatsQueryDTO query) {// 1. 查询基础数据List<EmploymentStats> statsList = statsMapper.queryEmploymentStats(query);// 2. 计算总体就业率BigDecimal totalRate = calculateTotalRate(statsList);// 3. 计算同比/环比Map<String, BigDecimal> compareData = calculateCompareData(query);// 4. 构建趋势数据List<TrendPointVO> trendData = buildTrendData(query);return EmploymentOverviewVO.builder().employmentRate(totalRate).yearOnYear(compareData.get("yearOnYear")).monthOnMonth(compareData.get("monthOnMonth")).trendData(trendData).build();}private List<TrendPointVO> buildTrendData(StatsQueryDTO query) {// 1. 获取时间范围Date startDate = DateUtils.addMonths(new Date(), -12);Date endDate = new Date();// 2. 查询趋势数据List<EmploymentStats> trendList = statsMapper.queryTrendData(query.getSchoolId(), startDate, endDate);// 3. 按月份聚合数据return trendList.stream().collect(Collectors.groupingBy(stats -> stats.getYear() + "-" + stats.getMonth(),Collectors.averagingDouble(EmploymentStats::getEmploymentRate))).entrySet().stream().map(entry -> new TrendPointVO(entry.getKey(), entry.getValue())).collect(Collectors.toList());}
}
2.2 薪资分析
@Service
public class SalaryAnalysisServiceImpl implements SalaryAnalysisService {public SalaryAnalysisVO analyzeSalary(AnalysisQueryDTO query) {// 1. 计算薪资区间分布List<SalaryRangeVO> rangeList = calculateSalaryRange(query);// 2. 计算专业薪资对比List<MajorSalaryVO> majorList = compareMajorSalary(query);// 3. 计算行业薪资水平List<IndustrySalaryVO> industryList = calculateIndustrySalary(query);return SalaryAnalysisVO.builder().rangeDistribution(rangeList).majorComparison(majorList).industryLevel(industryList).build();}private List<SalaryRangeVO> calculateSalaryRange(AnalysisQueryDTO query) {// 1. 定义薪资区间List<SalaryRange> ranges = Arrays.asList(new SalaryRange(0, 5000),new SalaryRange(5000, 10000),new SalaryRange(10000, 15000),new SalaryRange(15000, 20000),new SalaryRange(20000, Integer.MAX_VALUE));// 2. 统计各区间人数List<Map<String, Object>> stats = deliveryMapper.statSalaryRange(query.getYear(),query.getSchoolId());// 3. 计算占比return calculateProportions(stats, ranges);}
}
2.3 行业分布分析
@Service
public class IndustryAnalysisServiceImpl implements IndustryAnalysisService {public IndustryAnalysisVO analyzeIndustryDistribution(AnalysisQueryDTO query) {// 1. 查询行业分布数据List<IndustryDistribution> distributionList = distributionMapper.queryIndustryDistribution(query);// 2. 计算TOP10行业List<IndustryProportionVO> top10 = calculateTop10Industries(distributionList);// 3. 计算行业发展趋势List<IndustryTrendVO> trendList = calculateIndustryTrend(query);return IndustryAnalysisVO.builder().industryTop10(top10).industryTrend(trendList).build();}@Cacheable(value = "industryTrend", key = "#query.year")private List<IndustryTrendVO> calculateIndustryTrend(AnalysisQueryDTO query) {// 1. 获取近5年数据List<IndustryDistribution> historyData = distributionMapper.queryHistoryDistribution(query.getYear() - 5, query.getYear());// 2. 按行业分组Map<String, List<IndustryDistribution>> industryMap = historyData.stream().collect(Collectors.groupingBy(IndustryDistribution::getIndustry));// 3. 计算增长率return industryMap.entrySet().stream().map(entry -> {String industry = entry.getKey();List<IndustryDistribution> industryData = entry.getValue();BigDecimal growthRate = calculateGrowthRate(industryData);return new IndustryTrendVO(industry, growthRate);}).collect(Collectors.toList());}
}

3. 数据可视化实现

// 使用ECharts实现可视化图表
const employmentChart = {initEmploymentRate(data) {const chart = echarts.init(document.getElementById('employment-rate'));const option = {title: {text: '就业率趋势分析'},tooltip: {trigger: 'axis'},xAxis: {type: 'category',data: data.map(item => item.month)},yAxis: {type: 'value',axisLabel: {formatter: '{value}%'}},series: [{name: '就业率',type: 'line',data: data.map(item => item.rate),markPoint: {data: [{type: 'max', name: '最大值'},{type: 'min', name: '最小值'}]}}]};chart.setOption(option);},initSalaryDistribution(data) {const chart = echarts.init(document.getElementById('salary-dist'));const option = {title: {text: '薪资分布'},tooltip: {trigger: 'item',formatter: '{b}: {c} ({d}%)'},series: [{type: 'pie',radius: ['50%', '70%'],data: data.map(item => ({name: item.range,value: item.count}))}]};chart.setOption(option);}
};

4. 数据导出功能

@Service
public class DataExportServiceImpl implements DataExportService {public void exportEmploymentStats(ExportQueryDTO query, HttpServletResponse response) {// 1. 查询数据List<EmploymentStats> statsList = statsMapper.queryForExport(query);// 2. 创建Excel工作簿Workbook workbook = new XSSFWorkbook();Sheet sheet = workbook.createSheet("就业统计");// 3. 创建表头Row headerRow = sheet.createRow(0);String[] headers = {"统计年月", "专业", "毕业人数", "就业人数", "就业率", "平均薪资"};for (int i = 0; i < headers.length; i++) {Cell cell = headerRow.createCell(i);cell.setCellValue(headers[i]);}// 4. 填充数据int rowNum = 1;for (EmploymentStats stats : statsList) {Row row = sheet.createRow(rowNum++);row.createCell(0).setCellValue(stats.getYear() + "-" + stats.getMonth());row.createCell(1).setCellValue(stats.getMajorName());row.createCell(2).setCellValue(stats.getTotalStudents());row.createCell(3).setCellValue(stats.getEmployedCount());row.createCell(4).setCellValue(stats.getEmploymentRate() + "%");row.createCell(5).setCellValue(stats.getAvgSalary());}// 5. 导出文件response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");response.setHeader("Content-Disposition", "attachment; filename=employment_stats.xlsx");workbook.write(response.getOutputStream());}
}

以上是学生模块和数据分析模块的详细设计。主要特点包括:

  1. 学生模块:
  • 完整的简历管理功能
  • 基于Elasticsearch的职位搜索
  • 完善的投递跟踪机制
  1. 数据分析模块:
  • 多维度的统计分析
  • 可视化图表展示
  • 数据导出功能

技术亮点:

  • 使用Redis缓存热点数据
  • 使用ECharts实现数据可视化
  • 采用POI处理Excel导出
  • 实现数据实时统计和离线分析

相关文章:

Java全栈项目 - 校园招聘信息平台

项目介绍 校园招聘信息平台是一个面向高校学生和企业的双向服务平台。该系统帮助企业发布招聘信息,方便学生查询职位并投递简历,同时为学校就业部门提供就业数据分析功能。 技术栈 后端 Spring Boot 2.xSpring SecurityMyBatis PlusMySQL 8.0RedisRabbitMQ 前端 Vue.js 2…...

java导出

请求头获取responseimport com.alibaba.excel.EasyExcel; import com.alibaba.excel.ExcelWriter; import com.alibaba.excel.write.metadata.WriteSheet;PostMapping("excel/export") ApiOperation(value "党员档案导出", httpMethod "POST")…...

【嵌入式系统】期末试题库,ARM处理器,CortexM3内核,USART,EXTI,GPIO

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...

arcgisPro相接多个面要素转出为完整独立线要素

1、使用【面转线】工具&#xff0c;并取消勾选“识别和存储面邻域信息”&#xff0c;如下&#xff1a; 2、得到的线要素&#xff0c;如下&#xff1a;...

QTday1

#include "mywidget.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent) {//设置窗口标题this->setWindowTitle("向日葵远程控制");//设置窗口图标this->setWindowIcon(QIcon("C:\\Users\\Hasee\\Desktop\\pictrue\\mypicture\\logo.png&…...

SAP ALV选择列排序时弹出定义排序顺序窗口问题

需求场景 使用REUSE_ALV_GRID_DISPLAY_LVC生成ALV&#xff0c;发现一个问题&#xff1a;使用it_events的时候选择列排序时会弹出定义排序顺序窗口&#xff0c;如下图所示。&#xff08;正常选择某一列再使用排序功能时会直接排序&#xff0c;不用再选择列&#xff09; CLASS l…...

CSS Backgrounds(背景)

CSS Backgrounds(背景) Introduction(介绍) CSS backgrounds play a crucial role in web design, allowing developers to apply colors, images, and other decorative elements to the background of HTML elements. This enhances the visual appeal of web pages and he…...

欧拉计划 Project Euler 27 题解

欧拉计划 Problem 27 题解 题干思路code 题干 思路 可以先筛1e6的素数出来然后暴力找即可&#xff0c;具体思路看代码 code #include <bits/stdc.h>using namespace std;using ll long long;const int N 1e6 5; bool vis[N]; int pri[N];void getPrime() {memset(v…...

迁移学习--fasttext概述

迁移学习 1、fasttext概述 作为NLP工程领域常用的工具包, fasttext有两大作用&#xff1a;进行文本分类、训练词向量 正如它的名字, 在保持较高精度的情况下, 快速的进行训练和预测是fasttext的最大优势。fasttext工具包中内含的fasttext模型具有十分简单的网络结构。使用fa…...

【数字信号处理】数字信号处理试题及答案,离散序列,Z变换,傅里叶变换

关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...

CNN、RNN、LSTM和Transformer之间的区别和联系

文章目录 CNN、RNN、LSTM和Transformer之间的区别和联系前言CNN&#xff08;卷积神经网络&#xff09;RNN&#xff08;循环神经网络&#xff09;LSTM&#xff08;长短期记忆网络&#xff09;Transformer四者之间的联系与区别Yolo算法简介Yolo和CNN的关系YOLO各版本 CNN、RNN、L…...

springboot448教学辅助系统(论文+源码)_kaic

摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#x…...

用QT制作的倒计时软件

一、pro代码 RC_ICONS countdown.ico 二、mainwindow.cpp代码 #include "mainwindow.h" #include "ui_mainwindow.h"#include <QDateTime> #include <QMessageBox> #include <QSettings>MainWindow::MainWindow(QWidget *parent): QM…...

基于 mzt-biz-log 实现接口调用日志记录

&#x1f3af;导读&#xff1a;mzt-biz-log 是一个用于记录操作日志的通用组件&#xff0c;旨在追踪系统中“谁”在“何时”对“何事”执行了“何种操作”。该组件通过简单的注解配置&#xff0c;如 LogRecord&#xff0c;即可实现接口调用的日志记录&#xff0c;支持成功与失败…...

docker容器的安装以及用法

1、了解docker 1.1、docker是什么 Docker 是一个开源的应用容器引擎&#xff0c;基于 Go 语言 并遵从 Apache2.0 协议开源。 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的 Linux 机器上&#xff0c;也可以实现…...

Java中的Consumer接口应该如何使用(通俗易懂图解)

应用场景&#xff1a; 第一次程序员A写好了个基础的遍历方法&#xff1a; public class Demo1 {public static void main(String[] args) {//假设main方法为程序员B写的,此时需要去调用A写好的一个遍历方法//1.如果此时B突然发现想将字符串以小写的形式打印出来&#xff0c;则…...

D102【python 接口自动化学习】- pytest进阶之fixture用法

day102 pytest的usefixtures方法 学习日期&#xff1a;20241219 学习目标&#xff1a;pytest基础用法 -- pytest的usefixtures方法 学习笔记&#xff1a; fixture调用方法 实际应用 总结 pytest.mark.usefixtures(func)&#xff0c;pytest的usefixtures方法&#xff0c;无…...

从零玩转CanMV-K230(4)-小核Linux驱动开发参考

前言 K230 芯片是一款基于 RISC-V 架构的端侧 AIoT 芯片&#xff0c;包含两个核心&#xff1a; CPU 1: RISC-V 处理器&#xff0c;1.6GHz&#xff0c;32KB I-cache, 32KB D-cache, 256KB L2 Cache&#xff0c;128bit RVV 1.0扩展 CPU 0: RISC-V 处理器&#xff0c;0.8GHz&am…...

上汽大通汽车CAN数据解析开发服务及技术商用领域详细解析

上汽大通G90是一款集豪华、科技与舒适于一身的中大型MPV&#xff0c;号称“国产埃尔法”。在国内市场&#xff0c;作为“卷王”的G90主要面向中大型MPV市场&#xff0c;满足家庭出行、商务接待和客运租赁等多元化场景需求&#xff0c;在国内市场上取得了不错的销售成绩。在海外…...

基于SCUI的后台管理系统

一、SCUI Admin 官方地址&#xff1a;https://python-abc.xyz/scui-doc/ 高性能中后台前端解决方案&#xff0c;基于 Vue3、elementPlus 持续性的提供独家组件和丰富的业务模板帮助你快速搭建企业级中后台前端任务。 预览地址&#xff1a;https://python-abc.xyz/scui-doc/de…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)

引言 在人工智能飞速发展的今天&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;已成为技术领域的焦点。从智能写作到代码生成&#xff0c;LLM 的应用场景不断扩展&#xff0c;深刻改变了我们的工作和生活方式。然而&#xff0c;理解这些模型的内部…...