当前位置: 首页 > 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…...

使用频谱分析仪:RBW,Res BW,分辨率带宽;Sweep,扫描;noise floor,底噪,如何降低底噪?

RBW与Sweep的定义及其特性阐述&#xff1a; Res BW&#xff0c;即Resolution Bandwidth&#xff08;分辨率带宽&#xff09;&#xff0c;是衡量仪器分辨信号细节能力的重要参数。当RBW的数值越小&#xff0c;意味着像素点的尺寸更为精细&#xff0c;从而能够观察到更为细微的信…...

项目管理工具Maven(一)

Maven的概念 什么是Maven 翻译为“专家”&#xff0c;“内行”Maven是跨平台的项目管理工具。主要服务于基于Java平台的项目构建&#xff0c;依赖管理和项目信息管理。什么是理想的项目构建&#xff1f; 高度自动化&#xff0c;跨平台&#xff0c;可重用的组件&#xff0c;标准…...

阿里云ESC服务器一次性全部迁移到另一个ESC

摘要&#xff1a; 在云计算时代&#xff0c;服务器迁移是企业优化资源配置、提升业务灵活性的常见需求。本文将详细介绍如何将阿里云ECS&#xff08;Elastic Compute Service&#xff09;服务器一次性迁移到另一个ECS实例。整个迁移过程分为四个关键步骤&#xff1a; 创建自定义…...

搭建分布式Kafka集群

title: 搭建分布式Kafka集群 date: 2024-12-1 14:00:00 categories: - 服务器 tags: - Kafka - 大数据搭建分布式Kafka集群 在主节点上安装Kafka&#xff1b; Kafka使用Zookeeper服务器来存储元数据信息 本次实验环境&#xff1a;Centos 7-2009、Hadoop-3.1.4、JDK 8、Zookeep…...

【后端面试总结】深入解析进程和线程的区别

在操作系统和并发编程中&#xff0c;进程和线程是两个核心概念。它们各自承担着不同的职责&#xff0c;并在多任务处理中发挥着关键作用。本文将从定义、特性、应用场景以及优缺点等多个方面对进程和线程进行详细对比&#xff0c;帮助读者深入理解它们之间的区别。 一、进程和…...

java版电子招投标采购|投标|评标|竞标|邀标|评审招投标系统源码

招投标管理系统是一款适用于招标代理、政府采购、企业采购和工程交易等领域的企业级应用平台。该平台以项目为主线&#xff0c;从项目立项到项目归档&#xff0c;实现了全流程的高效沟通和协作。通过该平台&#xff0c;用户可以实时共享项目数据信息&#xff0c;实现规范化管理…...

SSM 赋能 Vue 助力:新锐台球厅管理系统的设计与实现的辉煌之路

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常适…...

C++ 并发专题 - C++线程同步的几种方法

一&#xff1a;概述 线程同步是多线程编程中的一个重要概念&#xff0c;它用于控制多个线程之间对共享资源的访问&#xff0c;避免竞态条件&#xff08;race condition&#xff09;和数据不一致的问题。线程同步确保在多线程环境中&#xff0c;多个线程访问共享数据时能够按照某…...

使用Python脚本进行编写批量根据源IP进行查询的语句用于态势感知攻击行为的搜索

使用Python脚本进行编写批量根据源IP进行查询的语句 以下根据ip-list集里面的IP地址&#xff08;可以自行扩充&#xff09;&#xff0c;然后采用srcaddress "{ip}" or 的形式进行打印并存储在路径为&#xff1a;桌面的IOC结果.txt --------------------------代码如…...

Python中的zip/unzip:像拉拉链一样组合数据的艺术

今天让我们一起探讨Python中一个优雅而强大的内置功能&#xff1a; zip 和 unzip 。听名字就知道&#xff0c;它就像我们衣服上的拉链一样&#xff0c;能把两边的数据完美地咬合在一起。 从一个有趣的例子开始 想象你正在开发一个班级管理系统。每个学生都有名字、成绩和评语…...