项目 |
内容 |
课程班级博客链接 |
|
这个作业要求链接 |
|
我的课程学习目标 |
能够制定好PSP,根据其要求完成整个系统界面的规划,构建 |
这个作业在哪些方面帮助我实现学习目标 |
复习了GUI界面和数据库的知识,也对java语言进行了复习和加固 |
项目Github的仓库链接地址 |
一、实验目的与要求
(1)掌握软件项目个人开发流程。
(2)掌握Github发布软件项目的操作方法。
二、实验内容和步骤
1、项目开发背景简介:
2019年12月末,中国武汉发生新型冠状病毒(2019-nCoV) 感染的肺炎疫情,为遏制疫情蔓延,有效切断病毒传播途径,在中央政府指导下,各级政府部分采取了一系列防控措施: 2020年1 月23 日10时起对武汉“封城”,全国 31个省市也相继实施了严格的防控措施;全国各省市向武汉和湖北派遣医疗队参与救治工作;在全国范围内调配口罩、防护服、药品等急需的医疗资源支援武汉;指导和督促全国范围内拥有医疗物资生产资质的企业尽快恢复生产能力;定向拨付专项财政资金用于疾病防控;从其他省份调集物资保障武汉市民日常生活。
值得一提的是,中国互联网企业在此次疫情防控中发挥了社会治理方面的重要作用。以腾讯为例,围绕应对疫情管控需求开发了十一款产品。其中疫情在线问诊功能,对于减少发热病人之间的相互交叉感染具有重要的作用,患者在家通过互联网向在线医生问诊,减少了病毒传播或感染的风险;谣言粉碎对于公众采取理性态度看待疫情的发展具有重要意义。滴滴出行还在武汉专门组建车队,服务于医护人员的通勤,这在实施交通管制的武汉具有重要作用。此外,还有新型肺炎确诊患者同行程查询工具,用户只需要输入自己所乘坐交通工具的时间和班次,就可以确认是否与被确诊感染者同行,提前做好自我隔离和就诊工作。在疫情防控中,中国互联网企业不仅发展壮大,在承担社会责任方面也越来越成熟。
为有效配合防控机构有关疫情信息的采集、统计与排查,我校开发了教职工/学生疫情上报系统,该系统由教职工疫情每日上报、学生疫情每日上报、二级部门疫情每日汇总表、疫情防控填报统计四个子系统组成。实现对我校各类人员基本情况、所在区域及活动轨迹及健康状况的信息收集。师生通过我校企业微信服务大厅访问该系统进行远程信息填报。
任务1:陈述学生疫情每日上报子系统使用体验;
- 在使用时候,我觉得有点不太方便,如果可以像钉钉一样,一打开界面就能自动弹出打卡信息表会比较好;
- 界面有点简单,不够美观;
- 可以自动记录填写信息,不必每天都去重复填写,较为方便。
- 没有提醒模式,比较容易忘记打卡。
任务2:总结详细阅读《构建之法》第1-2章、结合第2章2.3节所述PSP流程,开发一款你自己心目中的西北师范大学学生疫情每日填报系统。
你可在以下两类开发要求选择一种完成项目开发任务:
第一类开发要求:
有一个数据文件,保存了100天 2000 个教职工/学生的所有防疫信息,请设计一个命令行程序, 支持查询某人在某一天的疫情情况, 查询某种数据的周/月的疫情统计情况,并用柱状图显示统计结果。
第二类开发要求:
1. 系统可采集学生疫情有效信息;
2. 系统支持用户在线使用;
3. 每日只可填报一次,提交后无法修改,每日十点疫情信息填报截止;
4. 各学院指定负责人登录系统,可查看本学院学生填报的汇总数据,可点击查看学生联系方式、班主任联系方式,学院负责人核实本院所有学生数据后,将数据提交给学校防控办;
5. 学校防控办指定负责人登录《西北师范大学疫情防控信息统计》子系统,可浏览所有学生填报汇总数据清单,通过【导出】可获取疫情数据的EXCEL文件。
任务3:完成任务2项目开发,将项目源码的完整工程文件提交到本人注册Github账号的项目仓库中。
对于以上两个题目,我选择了任务二:
1、需求分析
- 系统可采集学生疫情有效信息;
- 系统支持用户在线使用;
- 每日只可填报一次,提交后无法修改,每日十点疫情信息填报截止;
- 各学院指定负责人登录系统,可查看本学院学生填报的汇总数据,可点击查看学生联系方式、班主任联系方式,学院负责人核实本院所有学生数据后,将数据提交给学校防控办;
- 学校防控办指定负责人登录《西北师范大学疫情防控信息统计》子系统,可浏览所有学生填报汇总数据清单,通过【导出】可获取疫情数据的EXCEL文件
2、功能设计
- 基本功能
(1)学生上报每日自己状况信息;
(2)两个权限:学生登录和管理员登录;
(3)每日只可填报一次,提交后无法修改,每日十点疫情信息填报截止;
(4)管理员后台查看控制所有信息;
(5)最终数据导出为Excel文件
- 扩展功能
(1)学生信息的增删改除;
(2)高级查询;
(3)对信息进行筛选;
(4)可以打印所有学生信息;
(5)边框可以侧边收缩功能;
(6)刷新界面按钮;
(7)系统通知栏
(8)验证码
3、设计实现
- 学生:可以采集学生疫情有效信息,查询,添加等功能
- 管理人员:登录后台,查看所有信息,筛选,打印,导出等功能
4、测试运行
- 基本功能
(1)学生上报每日自己状况信息;
(2)两个权限:学生登录和管理员登录;
(3)每日只可填报一次,提交后无法修改,每日十点疫情信息填报截止;
(4)管理员后台查看控制所有信息;
(5)最终数据导出为Excel文件
- 扩展功能
(1)学生信息的增删改除;
(2)高级查询;
(3)对信息进行筛选;
(4)可以打印所有学生信息;
(5)边框可以侧边收缩功能(前面那个键);
(6)刷新界面按钮(后面那个键);
(7)系统通知栏
(8)验证码
(9)小日历
5、关键代码片段(连接服务器代码)
package com.zywl.utils; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; /** * ftp上传下载工具类 */ public class FtpUtil { /** * Description: 向FTP服务器上传文件 * @param host FTP服务器hostname * @param port FTP服务器端口 * @param username FTP登录账号 * @param password FTP登录密码 * @param basePath FTP服务器基础目录 * @param filePath FTP服务器文件存放路径。例如分日期存放:/2019/01/01。文件的路径为basePath+filePath * @param filename 上传到FTP服务器上的文件名 * @param input 输入流 * @return 成功返回true,否则返回false */ public static boolean uploadFile(String host, int port, String username, String password, String basePath, String filePath, String filename, InputStream input) { boolean result = false; FTPClient ftp = new FTPClient(); try { int reply; ftp.connect(host, port);// 连接FTP服务器 // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器 ftp.login(username, password);// 登录 reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; } //切换到上传目录 if (!ftp.changeWorkingDirectory(basePath+filePath)) { //如果目录不存在创建目录 String[] dirs = filePath.split("/"); String tempPath = basePath; for (String dir : dirs) { if (null == dir || "".equals(dir)) { continue; } tempPath += "/" + dir; if (!ftp.changeWorkingDirectory(tempPath)) { if (!ftp.makeDirectory(tempPath)) { return result; } else { ftp.changeWorkingDirectory(tempPath); } } } } //设置上传文件的类型为二进制类型 ftp.setFileType(FTP.BINARY_FILE_TYPE); //上传文件 if (!ftp.storeFile(filename, input)) { return result; } input.close(); ftp.logout(); result = true; } catch (IOException e) { e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ioe) { } } } return result; } /** * Description: 从FTP服务器下载文件 * @param host FTP服务器hostname * @param port FTP服务器端口 * @param username FTP登录账号 * @param password FTP登录密码 * @param remotePath FTP服务器上的相对路径 * @param fileName 要下载的文件名 * @param localPath 下载后保存到本地的路径 * @return */ public static boolean downloadFile(String host, int port, String username, String password, String remotePath, String fileName, String localPath) { boolean result = false; FTPClient ftp = new FTPClient(); try { int reply; ftp.connect(host, port); // 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器 ftp.login(username, password);// 登录 reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); return result; } ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录 FTPFile[] fs = ftp.listFiles(); for (FTPFile ff : fs) { if (ff.getName().equals(fileName)) { File localFile = new File(localPath + "/" + ff.getName()); OutputStream is = new FileOutputStream(localFile); ftp.retrieveFile(ff.getName(), is); is.close(); } } ftp.logout(); result = true; } catch (IOException e) { e.printStackTrace(); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ioe) { } } } return result; } //String filepath = "http://39.96.26.57/jieagtFile/2019/11/14/1573742273542921.xlsx"; //String fileName = "1573742273542921.xlsx"; //boolean res = FtpUtil.downloadFile2(response, fileName, filepath); public static boolean downloadFile2(HttpServletResponse response, String filename, String filepath) { try { //设置响应头,控制浏览器下载该文件 response.setHeader("content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8")); //读取要下载的文件,保存到文件输入流 URL url = new URL(filepath); URLConnection connection = url.openConnection(); InputStream in = connection.getInputStream(); // BufferedReader br = new BufferedReader(new InputStreamReader(in,"UTF-8")); //创建输出流 OutputStream out = response.getOutputStream(); // BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); byte[] buf = new byte[1024]; int len = 0; String str = null; StringBuffer sb = new StringBuffer(); //循环将输入流中的内容读取到缓冲区当中 while ((len = in.read(buf)) != -1) { //输出缓冲区的内容到浏览器,实现文件下载 // bw.write(str); // bw.newLine(); out.write(buf, 0, len); } // bw.close(); out.close(); // br.close(); in.close(); return true; } catch (IOException e) { e.printStackTrace(); } return false; } public static void main(String[] args) { try { FileInputStream in=new FileInputStream(new File("E:/a.png")); boolean flag = uploadFile("192.168.17.129", 21, "ftpuser", "ftpuser", "/home/ftpuser/","/", "abc1.png", in); System.out.println(flag); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
6、总结:由于设置的类比较多,在测试阶段,出了不少错误,相互关联,容易出错,由于技术有限,现阶段只能改为以上的界面,也没有用到更好的技术实现软件开发的模块化方法,而且还有很多内容有问题,由于时间有限,所以在课下的的时间里再加修改,希望能更加的完善。
7、PSP
PSP2.1 | 内容 | 计划完成需要的时间(min) | 实际完成需要的时间(min) |
---|---|---|---|
Planning | 计划 | 40 | 30 |
Estimate | 估计这个任务需要多少时间,并规划大致工作步骤 | 30 | 60 |
Development | 开发 | 1500 | 1800 |
Analysis | 需求分析 (包括学习新技术) | 120 | 150 |
Design Spec | 生成设计文档 | 40 | 30 |
Design Review | 设计复审 (和同学审核设计文档) | / | / |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 30 | 30 |
Design | 具体设计 | 300 | 250 |
Coding | 具体编码 | 600 | 900 |
Code Review | 代码复审 | 30 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 120 |
Reporting | 报告 | 100 | 120 |
Reporting | 报告 | 60 | 90 |
Test Report | 测试报告 | 20 | 20 |
Size Measurement | 计算工作量 | 20 | 30 |
Postmortem & Process Improvement Plan | 事后总结 ,并提出过程改进计划 | 20 | 20 |