一、前情提要

根据通知,每天从每个年级抽22%的人数去做核酸,五天做到全覆盖,那么问题来了,前四天做完之后是88%的人做完了,第五天12%的人没做,剩下的10%就要从做过的人中抽取,那么要怎么实现,而且要公平呢?

然后,这里又附加了一个要求,从每个年级具体到每个班级,即每个班每天抽取22%。然后我看了看他给的excel,发现有某几个人,数据跟他班的其他人不在一块,emmm……难度进一步提升。

二、整体设计+源代码

【前端】

前端部分:提交总表+开始轮次+运行轮次
懒得美化,纯html实现功能

<!DOCTYPE html>
<html>
<head><title>核酸检测抽取</title>
</head>
<body>
<form method="post" style="text-align: center" action="/getTimes" enctype="multipart/form-data">起始轮次:<input type="text" name="startTime"><br>(即已经进行了几轮核酸检测了,五天一轮,假设你已经执行三轮了,你就填4)<br>执行伦次:<input type="text" name="turn"><br>(即你要获取几轮的数据)<br><input type="file" name="file"><br><input type="submit" value="提交">
</form>
</body>
</html>

【pom文件】

3+的插件有毛病,改成2的能跑就完事了

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.6</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.zx</groupId><artifactId>fycq</artifactId><version>1</version><name>fycq</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.21</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId><version>2.4.3</version></plugin><!--            主要就是为了引入ByteOutputStream--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>${java.version}</source><target>${java.version}</target><encoding>UTF-8</encoding><compilerArguments><verbose/><bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar</bootclasspath></compilerArguments></configuration></plugin></plugins></build>
</project>

【模型层】

只是用于存储临时数据,因为我redis是个半吊子,所以就用了mysql数据库
@ExcelPeoperty是规定表头,@ExcelIgnore是写excel不写这几个字段

Stu.java

用于临时存储表中信息,没主键
加了个uuid以防线程问题,当然是后话了

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@TableName("stu")
public class Stu {@ExcelProperty("年级")private Integer year;@ExcelProperty("专业班级")private String cl;@ExcelProperty("姓名")private String name;@ExcelProperty("学号")private String num;@ExcelIgnoreprivate String uuid;@ExcelIgnoreprivate Integer avg;//该班级多少个
}
ClassNums.java

主要用于Group By提取班级信息

@Data
public class ClassNums {//专业班级private String cl;//班级人数private Integer ct;
}

【持久层】

用的Mybatis-Plus
uuid还是为了防止线程问题(虽说后来感觉可能多此一举)
sql语句是查出所有班级以及对应班级人数
加@Repository是出于不想看到自动注入时候有红色下滑波浪线

@Repository
public interface StuMapper  extends BaseMapper<Stu> {@Select("select cl,count(*) ct from stu where uuid=#{uuid, jdbcType=VARCHAR} GROUP BY cl ")public List<ClassNums> findByClass(@Param("uuid")String uuid);
}

【服务层】

这里就麻烦一点。
里面有三个方法,逐个细说。

deleteAll(String uuid)方法

主要是将本次请求产生的临时数据删除

getForTimes方法

首先是传入的参数:file:总表excel;st:开始轮次;turn:执行轮次;response:用于获取本次请求的outstream,将压缩包写入。

整体代码分两个部分:数据处理、写入文件流
数据处理阶段

数据处理阶段
本阶段我是打算以 Map<Integer,Map<String,Queue<Stu>>> map = new HashMap<>();来存储所有的数据,具体关系为:年级 -》 班级 -》 学生队列``,之后开辟空间(这里纯属偷懒,假设只存在2018-2021年级,具体可以自己写个sql只读取年级,然后遍历即可)。
首先找到本次所有的班级以及班级对应的人数(上面sql语句起作用了),之后遍历每个班级,先计算每个班级应该每天测多少个人(四舍五入),然后查出该班级学生的列表,然后将该班级的学生塞入一个队列中,让其循环起来,因为是事先设置了一个开始轮次,即已经轮了多少次了,那就先在这个队列中倒腾一下即可。
最后就是将年级、班级、倒腾后的队列塞入map中就ok。

文件生成阶段(包括后续数据处理)
这里用的是java.util里面的ZipOutputStream类来打压缩包,读写excel都是用的excel,ZipOutStream使用需要用到ByteOutputStream,如果用的poi的话是直接就包含了的,但没用poi就得在pom中导一下,见前文pom。
主要就是循环 turn 次来生成 turn*4 个文件,然后压到一个压缩包里面提供下载,具体操作看代码,循环就完事了,中间调用setExcel()方法来写excel中的sheet,最后都是压入response提供下载。

setExcel方法

写五个批次,为一个excel生成五个sheet,顺便倒腾循环队列。

@Service
public class ExcelService {@Autowiredprivate StuMapper mapper;@Transactionalpublic void getForTimes(MultipartFile file, Integer st, Integer turn, HttpServletResponse response){if(st==null) st = 0;if(turn==null) turn = 1;String uuid = UUID.randomUUID().toString().replaceAll("-","");try {EasyExcel.read(file.getInputStream(), Stu.class,new ExcelListener(mapper,uuid)).sheet().doRead();/** 开辟空间 年级 -》 班级 -》 学生队列 */Map<Integer,Map<String,Queue<Stu>>> map = new HashMap<>();map.put(2018,new HashMap<String,Queue<Stu>>());map.put(2019,new HashMap<String,Queue<Stu>>());map.put(2020,new HashMap<String,Queue<Stu>>());map.put(2021,new HashMap<String,Queue<Stu>>());/** 找到本次所有班级以及对应班级的人数 */List<ClassNums> list = mapper.findByClass(uuid);List<Stu> stus = null;Queue<Stu> queue = null;HashMap<String, Queue<Stu>> clMap = null;for(ClassNums n:list){//遍历每个班级int stuNums = (int) Math.round(n.getCt()*0.22);//获取到该班级应该每天多少人String cl = n.getCl();//班级名QueryWrapper<Stu> wrapper = new QueryWrapper<>();wrapper.eq("cl",cl).eq("uuid",uuid);stus = mapper.selectList(wrapper);//找到该班级的所有学生if(!stus.isEmpty()){queue = new LinkedList<>();Integer year = stus.get(0).getYear();//年级//将该班级所有学生塞入队列,然后给每个人设置自己班级每次多少人for(Stu s:stus) { s.setAvg(stuNums); queue.offer(s); }//st为已经进行了多少轮了,循环让这些人先到队尾for(int i=0;i<st*5;i++){for(int j=0;j<stuNums;j++) {Stu s = queue.poll();queue.offer(s);}}//存储map.get(year).put(cl,queue);}}//turn轮 turn * 4 个文件,每个文件5个表ZipOutputStream zipOutputStream = new ZipOutputStream(response.getOutputStream());for(int i=1;i<=turn;i++){for(int y=2018;y<=2021;y++){clMap = (HashMap<String, Queue<Stu>>) map.get(y);ZipEntry entry = new ZipEntry(y+"-第"+i+"轮.xlsx");zipOutputStream.putNextEntry(entry);ByteOutputStream byteOutputStream = new ByteOutputStream();setExcel(byteOutputStream,clMap);byteOutputStream.writeTo(zipOutputStream);byteOutputStream.close();zipOutputStream.closeEntry();}}zipOutputStream.close();} catch (Exception e) {e.printStackTrace();}finally {deleteAll(uuid);}return R.OK();}@Transactionalvoid setExcel(ByteOutputStream byteOutputStream,HashMap<String,Queue<Stu>> clMap){ExcelWriter excelWriter = null;try {excelWriter = EasyExcel.write(byteOutputStream,Stu.class).build();Queue<Stu> queue = new LinkedList<>();for(int t=1;t<=5;t++){//做五批次的表WriteSheet writeSheet = EasyExcel.writerSheet((t-1),"第"+t+"批").build();List<Stu> s2018 = new ArrayList<>();//存储该年级该批次的表for(Map.Entry<String, Queue<Stu>> entry : clMap.entrySet()){Integer num = entry.getValue().peek().getAvg();queue = entry.getValue();for(int j=0;j<num;j++){Stu s = queue.poll();s2018.add(s);queue.offer(s);}}excelWriter.write(s2018,writeSheet);}}catch (Exception e){e.printStackTrace();}finally {if(excelWriter!=null){excelWriter.finish();}}}private void deleteAll(String uuid){//删除本次产生的临时数据QueryWrapper<Stu> wrapper = new QueryWrapper<>();wrapper.eq("uuid",uuid);mapper.delete(wrapper);}
}

【控制器】

@RestController
public class AController {@Autowiredprivate ExcelService excelService;@RequestMapping("/getTimes")public void getExcelForTimes(HttpServletRequest request,MultipartFile file, Integer startTime, Integer turn, HttpServletResponse response) throws UnsupportedEncodingException {response.setContentType("application/zip; charset=UTF-8");//返回客户端浏览器的版本号、类型String agent = request.getHeader("USER-AGENT");String downloadName = "核酸检测批次.zip";//针对IE或者以IE为内核的浏览器:if (agent.contains("MSIE") || agent.contains("Trident")) {downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");} else {downloadName = new String(downloadName.getBytes("UTF-8"), "ISO-8859-1");}response.setHeader("Content-disposition", "attachment;filename=" + downloadName);excelService.getForTimes(file, startTime-1, turn,response);}
}

【启动类】

@SpringBootApplication
@MapperScan(value = {"com.zx.fycq.dao"})
public class FycqApplication {public static void main(String[] args) {SpringApplication.run(FycqApplication.class, args);}
}

【配置文件】

server.port=端口号
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://你的地址和库?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2b8
spring.datasource.username=密码
spring.datasource.password=账号

核酸检测抽签系统(每次在每个班级选择%22)easyexcel+ZipOutputStream相关推荐

  1. 核酸检测识别系统——总章

    目录 核酸检测结果识别系统 源代码(FOR FREE) 产品介绍 产品功能 技术栈 使用说明 技术算法讲解 组成部分 easyocr opencv excel表和数据库 Pyecharts可视化界面 ...

  2. 计算机开机选择用户界面,win7系统每次开机都会出现选择操作系统界面的设置办法...

    win7系统使用久了,好多网友反馈说win7系统每次开机都会出现选择操作系统界面的问题,非常不方便.有什么办法可以永久解决win7系统每次开机都会出现选择操作系统界面的问题,面对win7系统每次开机都 ...

  3. 核酸检测识别系统——网站开发

    目录 前端 后端 总结 开发技术使用简单的三件套+jquery+后端PHP实现简单的文件收集功能,因为主要功能都是python实现,网站只是辅助收集报告而已,无需过多关注. 源代码:-system/W ...

  4. 核酸检测管理系统,核酸预约系统,核酸检测预约系统毕业设计作品

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于web网页的疫情核酸检查预约系统,整个网站项目使用了B/S架构,基于java的springboot框架下开发::通过后台设置医院信息.录入医 ...

  5. 从核酸检测平台崩盘看性能工程的范围

    近几年疫情肆虐,健康码系统和核酸检测系统成了民生的保障.在疫情张狂的时候,这类系统的稳定性.可用性是关键的技术支撑能力. 每个地方的健康码平台都或多或少地出现过问题,影响每个人的生活. 从我工作十几年 ...

  6. 核酸检测预约和结果查询系统

    一,绘制UML图 1.用例图: 本系统的使用者(User)主要分为用户(Patient)和管理者(Manager),用户无需登录,只需输入身份信息就可以预约核酸检测和查看检测结果.管理员需要正确输入密 ...

  7. xp计算机启动检测硬盘,让WinXP系统每次开机都能自检并修复硬盘

    用过WinXP系统的朋友都知道,每当电脑意外断电或者非法关机时,下次再开机系统会自动检测并修复硬盘,这个措施虽然花费了一点时间,不过对于硬盘的保护还是非常有效果的,能最大限度保护你硬盘中的数据,而在正 ...

  8. asp核酸检测预登记系统源码

    用asp开发的核酸检测预登记系统上线了,用户填写姓名,手机,身份证号,地址等信息后生成一个加密的二维码,管理员扫码后可以得到真实的二维码文字信息.主要为方便核酸采集统计托底等,也可以用作会议入场信息采 ...

  9. java基于安卓微信小程序的医院核酸检测预约挂号系统 uniapp 小程序

    医院核酸检测预约挂号的需求和管理上的不断提升,医院核酸检测预约挂号管理的潜力将无限扩大,医院核酸检测预约挂号微信小程序在业界被广泛关注,本网站及对此进行总体分析,将医院核酸检测预约挂号信息管理的发展提 ...

最新文章

  1. Luogu P6055 [RC-02] GCD(莫比乌斯反演,杜教筛)(这题乐死我了,真就图一乐呗)
  2. 使用Asp.net MVC, Jquery, Jquery UI构建基于Ajax的RIA应用.(更新Demo下载)
  3. centos 支持 ntfs格式
  4. jquery地址栏链接与a标签链接匹配添加样式!
  5. 用时间分类能量再用能量分类时间
  6. INNODB的锁的类型
  7. Linux实验三父子进程每隔3秒,实验三进程的创建和简单控制(学生分析.doc
  8. 27. 移除元素 golang
  9. java获取s3对象url_java-如何通过SDK设置S3对象的内容类型?
  10. Java面试问题:新的任务提交到线程池,线程池是怎样处理
  11. C++ 如何有效地使用对话框
  12. 微信经典飞机大战,承载多少人的回忆!
  13. python123平台第三周作业答案_python123第一周作业
  14. linux 下令chmod 755的意思
  15. 线性回归方程b保留几位小数_简单线性回归分析(python)
  16. java微信提现_如何做提现到微信和支付宝
  17. Python爬虫实战(6)-爬取QQ空间好友说说并生成词云(超详细)
  18. UML用例图中三种关系详解
  19. 硬派健身——健身先健脑
  20. linux私房菜总结(0-1)

热门文章

  1. iphone微信 电脑连接到服务器,简单几步,让 iPhone 无线访问 Windows 传文件
  2. 苹果ppt_苹果PPT动画真的太酷了~用PPT也能做出来吗?是的
  3. CUIT-2017 Re150 攻防世界
  4. Linux usb设备驱动
  5. 青龙2.10.13 稳定版+Ninja登录面板+傻妞+OneBot机器人 保姆级教程【2022/7/1】
  6. 章鱼未来之星获得25万美金奖励|章鱼加速器2022夏季创业营圆满落幕
  7. mysql gunzip 远程,Java 操作mysql 导入|导出 gzip|gunzip 工具类
  8. 案例分析 - 百度传课网易云课堂在线教育平台竞品分析
  9. python中的模块_Python中的模块 | 萧小寒
  10. 破碎的残阳,我们逆光【连载小说】- HashMap剖析