# Java企业框架 实验三 全球新型冠状病毒实时数据统计应用程序的设计与实现
**Repository Path**: yanliye/spring-boot-exp03-427yeziyin
## Basic Information
- **Project Name**: Java企业框架 实验三 全球新型冠状病毒实时数据统计应用程序的设计与实现
- **Description**: No description available
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-11-23
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 东莞理工学院网络空间安全学院
课程名称 :企业级开发框架专题 学期:2020秋季
实验名称:全球新型冠状病毒实时数据统计应用程序的设计与实现
实验序号:三
| 姓名:叶梓茵 | 学号:201841413427 | 班级:18网工4班 |
|---|---|---|
| 实验地址:学校 |实验日期:2020-11-09 | 指导老师:黎志雄 |
| 教师评语:XXX | 实验成绩:XXX | 百分制:XXX |
同组同学:无
### 一、 实验目的
1、 掌握使用Spring框架自带的RestTemplate工具类爬取网络数据;
2、 掌握使用Spring框架自带的计划任务功能;
3、 掌握使用Apache Commons CSV组件解释CSV文件;
4、 掌握Java 8的Stream API处理集合类型数据;
5、 了解使用模板引擎或前端框架展示数据。
### 二、 实验环境
1、 JDK 1.8或更高版本
2、 Maven 3.6+
3、 IntelliJ IDEA
4、 commons-csv 1.8+
### 三、 实验任务
1、 通过IntelliJ IDEA的Spring Initializr向导创建Spring Boot项目。
2、 添加功能模块:spring MVC、lombok、commons-csv等。
推荐使用commons-csv组件处理csv文件:

3、 爬取全球冠状病毒实时统计数据。(Java,Spring)
Gitee仓库的csv文件
4、 使用Spring框架自带的RestTemplate工具类爬取数据。
```java
public class Covid19DateService implements InitializingBean {
//将url设置为静态且不可更改的常量
private static final String Covid19_Date_URL = "https://gitee.com/dgut-sai/COVID-19/raw/master/csse_covid_19_data/csse_covid_19_time_series/time_series_covid19_confirmed_global.csv";
private final ArrayList regionStatsList = new ArrayList<>();
private Logger Log= LoggerFactory.getLogger(Covid19DateService.class); //日志记录
//设置每日凌晨1.更新任务,更新
@Scheduled(cron = "${yzy.Schedules.updateVirusDataCron}")
public void fetchCovid19Data() throws IOException{
regionStatsList.removeAll(regionStatsList); //初始化列表
if(regionStatsList.isEmpty()){
Log.info("初始化数据列表完成");
}
RequestEntity requestEntity = RequestEntity.get(URI.create(Covid19_Date_URL))
.headers(httpHeaders -> httpHeaders.add("User-Agent","yeziyin"))
.build();
ResponseEntity exchange = new RestTemplate().exchange(requestEntity,Resource.class);
Resource body = exchange.getBody();
```
5、 分析csv文件的数据结构,定义model类。
```java
package com.dgutnw.yeziyin.sbexp.exp03_covid19_realtimedate.models;
import lombok.Data;
@Data
public class RegionStats {
private String state; //州/省市
private String country; //国家
private int latestTotalSaes; //统计至当天共有病例
private int diffFromPrevDay; //与前一天对比差异
}
```
6、 使用Apache Commons CSV组件解释CSV文件。
```java
(接第4题 Covid19DateService() 后)
Reader readin;
if(body != null){
Log.info("数据拉取成功");
readin = new InputStreamReader(body.getInputStream());
Iterable records = CSVFormat.RFC4180.withFirstRecordAsHeader().parse(readin);
for (CSVRecord record : records) {
RegionStats model = new RegionStats();
model.setState(record.get("Province/State"));
model.setCountry(record.get("Country/Region"));
int latesttotal = Integer.parseInt(record.get(record.size() - 1));
int thedaybefore = Integer.parseInt(record.get(record.size() - 2));
model.setLatestTotalSaes(latesttotal);
model.setDiffFromPrevDay(latesttotal - thedaybefore);
regionStatsList.add(model);
}
}
}
```
7、 使用Spring框架自带的计划任务功能定时更新统计数据。


8、 要确保应用程序启动时,获取一次统计数据。
```java
// 程序启动时,自动拉取一次数据
@Override
public void afterPropertiesSet() throws Exception{
fetchCovid19Data();
}
```
9、 单元测试。
```java
//设置断言测试是否成功抓取csv文件
@Test
void TestCsvCatch(){
Resource csv = covid19DateService.getBody();
Assertions.assertNotNull(csv);
}
```
测试结果无报错:

```java
//测试是否解析数据成功
@Autowired
Covid19DateService covid19DateService;
@Test
void ServiceTest() {
try{
this.covid19DateService.fetchCovid19Data();
List TestList = covid19DateService.getRegionStatsList();
System.out.println("共爬取解析数据数:"+TestList.size());
System.out.println("前五条数据:"+TestList.subList(0,4)+"\n");
//打印出前五条数据
System.out.println("后五条数据:"+TestList.subList(TestList.size()-6,TestList.size()-1)+"\n");
//打印出后五条数据
} catch (IOException e) {
e.printStackTrace();
}
}
```
测试结果成功:

10、 定义Cotroller控制器。
```java
@Controller
public class HomeController {
@Autowired
Covid19DateService covid19DateService;
@RequestMapping("/{countryn}")
public String SearchCountry(Model model, @PathVariable("countryn") String country)
{
List RS ;
if(country==null || country.equals("all")){
RS= covid19DateService.getRegionStatsList();
}
else{//将查询结果收集为不可变的List集合
RS = covid19DateService.getRegionStatsList()
.parallelStream().filter(locationStats -> locationStats.getCountry().equals(country))
.collect(Collectors.toUnmodifiableList());
}
Date TimeAtNow = new Date();
int latestTotalCases;
int diffFromPrevDayTotal;
//求和
latestTotalCases= RS.stream().mapToInt(RegionStats::getLatestTotalSaes).sum();
diffFromPrevDayTotal= RS.stream().mapToInt(RegionStats::getDiffFromPrevDay).sum();
model.addAttribute("country",country);
model.addAttribute("ragionStats",RS);
model.addAttribute("datenow",TimeAtNow);
model.addAttribute("totalReportCases",latestTotalCases);
model.addAttribute("totalNewCases",diffFromPrevDayTotal);
return "index";
}
}
```
11、 定义前端数据展示页面。


### 四、 实验总结
这次实验主要是不熟悉爬取数据的部分,本来想尝试webclient,学习文档上的还是有些不熟悉,先用RestTemplate,感觉没有想象中的难上手。感觉老师的实验比较新,贴近生活实用也有趣。前端页面统计图的实现还不太熟悉,需要进一步学习,先编写了简单的列表样式,添加了搜索框。