这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/2020SpringW |
---|---|
这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/2020SpringW/homework/10456 |
这个作业的目标 | 采用web技术,结合寒假第二次作业的成果实现原型设计中的部分功能 |
结对学号 | 221701233、221701234 |
作业正文 | https://www.cnblogs.com/sillyby/p/12492953.html |
其他参考文献 |
Github仓库地址: https://github.com/WallofWonder/InfectStatisticWeb
代码规范链接:https://github.com/WallofWonder/InfectStatisticWeb/blob/master/codestyle.md
演示地址:阿里云 (初次加载比较慢,请耐心等待)
成果展示
全国疫情概览:
- 展示现有确诊、现有疑似、现有重症、累计确诊、累计治愈、累计死亡等数据
- 提供现有确诊、累计确诊的全国地图可视化展示
切换地图数据
省份详情:
单击地图上的省份进入省详情页面:
折线图的数据切换:
向下滚动可查看该省各市的疫情数据:
未完成的扩展功能页面:
包括疫情新闻、同程查询、谣言鉴别
结对过程
作业发布后,我们首先讨论的是采用什么技术和框架来实现,我们决定采用springboot+vue的前后端分离技术来实现作业的要求,原因是我们其中一人在寒假学习过springboot,另一人学习过vue,而且都没有用学到的知识真正搭建过一个像样的东西,正好能拿这次作业练练手。
确定好所采用的技术之后,第一个问题是如何获取数据,为了方便拿到数据我们采用了天行数据的接口
我们根据所采用的技术指定了代码规范,接下来就是进行分工:
- 221701233:后端、后端部分文档博客撰写、博客整合和发布
- 221701234:前端、前端部分文档博客撰写、云服务器部署
之后,我们开始进行协作的磨合,由于负责前端的同学git还不是很熟练,两人之前也从未接触过正式的git协作,我们花了两天的时间进行git的知识储备和协作测试,大致摸清了协作流程之后,开始上手开发。
由于是前后端分离开发,我们可以同时进行项目的推进,并在开发过程中交流保持进度同步,互相测试代码的功能,并且共同解决一些难以解决的问题。
实现了基础功能后,进行紧张的代码复审和部署测试操作,在这个过程中遇到了许许多多的小毛病,但最后还是逐个解决了,并合作完成博客撰写。
结对过程截图
遇到的主要困难以及克服过程
前后端跨域问题
分析:经过查找资料,这应该是前后端分离所导致的问题,由于前后端分别运行在不同端口,之间的数据交互属于跨域,而因为浏览器收到同源策略(不同的域名, 不同端口, 不同的协议不允许共享资源的,保障浏览器安全。)的限制,当前域名的js只能读取同域名下的窗口属性。
解决方案:前端请求接口时加上http://头即可。
刻苦铭心的经历——代码丢失
起因:ddl的前一天,前端同学undo了一次commit,再次commit的时候github只提交了新增文件,而没有提交已有代码的修改,此时前端同学又从GitHub拉取了一次代码,导致对已有代码的修改丢失,一个下午的努力似乎付诸东流。
解决:大家都很紧张,乱了阵脚,熬夜寻找解决方案,最后的解决方法却十分简单——通过IDE的历史记录回滚恢复修改的代码,并再次commit,真的是虚惊一场。
针对该次事件的反思:可能表达语言水平有限,没法体现出我们当时心态有多崩,不过这个问题也反映出了我们对git的不熟练,导致这一星期许多时间都用在解决git多人协作的问题上了,严重拖慢了进度,只勉强完成了基础功能,为了后续的学习和团队实践我们两人都需要抓紧熟练git多人协作的使用了。
云服务器部署问题
前端同学在搭建过程中的探索已经总结并写成了一篇博客,在先贴上博客链接吧
https://www.cnblogs.com/QEEZ/p/12501197.html
主要的问题概括如下:
- 后端链接数据库被拒绝访问,解决方法:linux数据库配置问题,安装时没有配好
- 前端请求资源失败,解决方法:修改前端请求中的localhost为服务器的公网ip。
设计实现
我们决定采用springboot+vue的前后端分离技术来实现作业的要求。
确定好所采用的技术之后,第一个问题是如何获取数据,为了方便拿到数据我们采用了天行数据的接口,同时为了减轻第三方接口压力进行数据的持久化,前端发送至后端的请求是面向数据库的,而后端负责从第三方接口定时获取数据维护数据库,同时因为第三方接口返回的json数据繁杂,不符合前端需要的数据格式,后端需要对其进行过滤和整理。
在前端的界面设计上大致遵循原型设计的风格,决定采用ElementUI组件库美化界面,同时嵌入Echarts完成对图表的绘制。
关键代码——后端
请求第三方接口的数据
初始化数据库时,为了获取过去20天的数据,需要以较高的频率调用第三方接口获取数据,用同一个apikey高频调用会出现不稳定情况,于是使用三个apikey分担压力。
/**
* @param httpUrl 请求接口
* @param httpArg 参数
* @param tag apiKey选择标识
* @return 返回结果
*/
public static String request(String httpUrl, String httpArg, int tag) {
BufferedReader reader = null;
String result = null;
StringBuffer sbf = new StringBuffer();
String apiKey = "";
if (tag == 0) {
apiKey = API_KEY0;
}
else if (tag == 1) {
apiKey = API_KEY1;
}
else if (tag == 2) {
apiKey = API_KEY2;
}
httpUrl = httpUrl + "?key="
+ apiKey
+ ((httpArg == null) ? "" : httpArg);
try {
URL url = new URL(httpUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
InputStream is = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
String strRead = null;
while ((strRead = reader.readLine()) != null) {
sbf.append(strRead);
sbf.append("\r\n");
}
reader.close();
result = sbf.toString();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
配置定时任务
为保证前端获取的数据的可靠性,设置每隔10分钟更新一次数据库。和启动时的初始化不同,定时任务只会更新当日数据,不会高频调用接口。
@Component
@Slf4j
public class ScheduledJob {
@Resource(name = "provinceServiceImpl")
ProvinceService provinceService;
@Resource(name = "cityServiceImpl")
CityService cityService;
@Resource(name = "nationServiceImpl")
NationService nationService;
private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/**
* 每10分钟更新一次数据库
*/
@Scheduled(cron = "0 */10 * * * ? ")
public void cronJob() {
log.info("=========================== >> 更新数据库...");
updateNationData();
updateProvinceDataToday();
upadateCityData();
log.info("=========================== >> 数据库更新完成。");
}
/**
* 应用启动时更新数据库
*/
@PostConstruct
public void updateAtStart() {
log.info("=========================== >> 更新数据库...");
updateNationData();
updateProvinceData();
upadateCityData();
log.info("=========================== >> 数据库更新完成。");
}
...
}
定时任务的截图