一、前情提要

根据通知,每天从每个年级抽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. MySQL复制经常使用拓扑结构具体解释
  2. 【万能小说分析】【python】【词频分析】【词频统计】【jieba】【matplotlib】【wordcloud】【绘图】
  3. python函数调用时所提供的参数可以是变量吗_Python函数一章,关于变量参数调用(何时使用*)记录,pytho,章节,可变,的,什么,时候...
  4. linux下recv 、send阻塞、非阻塞区别和用法
  5. 常用NTP网络时间服务器整理
  6. Javascript - demo 与 捷径
  7. 89c52串口发送接收小示例
  8. java captivate_flashremoting-java-win-en.exe
  9. 【果壳笔记】生物信息学——陈润生老师部分
  10. python暴力破解rar压缩文件
  11. 微信加好友CALL地址 3.4.5.27
  12. 置信度置信水平置信区间
  13. 最近流行的暴寒经典语句
  14. HTML最给力的入门教程
  15. python绘制一份完美的中国地图
  16. 中台技术爆发,这个软件定义中台专利指出了数字化转型路径
  17. 知乎问答:为什么现在又流行服务器端渲染html?
  18. MindSpore实现手写数字识别代码
  19. 2023年12306购票平台自动化购票一|解决登录问题
  20. const int INF=0x3f3f3f3f;——ACM中的无穷大常量

热门文章

  1. 如何做才能降低团队人员流失率?
  2. 基本概念--MAE、MSE和RMSE
  3. Mycat2.0搭建教程
  4. eureka上被down掉的服务手动up
  5. 教你技巧不让IP地址冲突干扰你的网络局域网
  6. 2022-2028中国真空电机市场现状研究分析与发展前景预测报告
  7. WinPcap免安装版(静默安装版) (程序员角度的实现相应逻辑)
  8. HTML5新标签及特性
  9. VS2015无法打开输入文件xxx.lib
  10. 如何将图片批量重命名001开始?