Java疫情数据分析系统3

SSM框架集成

 这是idea的常用快捷键,在代码编辑中会用到

一、新建包名

分层管理(MVC分层设计):

bean:管理一些实体类,大部分是跟数据库表存在着映射关系

common:管理一些工具类,或者公共类

controller:控制层,进行逻辑控制

mapper:数据访问层,通常对数据库进行CRUD

 service:业务逻辑层,完成业务逻辑的操作

数据访问顺序:

jsp前端页面直接和controller控制层进行数据交互

controller控制层访问service业务逻辑层

services业务逻辑层访问mapper数据层

二、主要代码

EpidemicApplicationInitializer类,对项目进行一个总的配置,替代了web.xml中的相关配置
package com.lintao.epidemic;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * 总配置文件,替代了web.xml中的相关配置
 */
public class EpidemicApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    /**
     * 用来配置ContextLoaderListener创建对应上下文的bean
     * @return
     */
    @Override
    protected Class<?>[] getRootConfigClasses() {
        //Spring相关配置
        return new Class[]{SpringConfig.class};
    }

    /**
     * 用于定义DispatcherServlet应用上下文的bean
     * @return
     */
    @Override
    protected Class<?>[] getServletConfigClasses() {
        //SpringMVC相关配
        return new Class[]{SpringMVCConfig.class};
    }

    /**
     * 配置拦截器
     * @return
     */
    @Override
    protected String[] getServletMappings() {
        //返回映射到DispatcherServlet的请求路径
        return new String[]{"/"};
    }
}
DateConverter工具类,用于转换日期格式
package com.lintao.epidemic.common;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date; /** * 日期转换器(将界面中拿到的字符串转换为日期) */ @Component public class DateConverter implements Converter<String, Date> { private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//举例:2020-05-08  @Override public Date convert(String s) { if(s == null || s.length()==0){ return null; } Date date = null; try { date = sdf.parse(s); } catch (ParseException e) { e.printStackTrace(); System.out.println("转换提交的参数"+s+"为日期值时出错:"+e.getMessage()); } return date; } }
EpidemicController,对疫情信息进行逻辑控制
package com.lintao.epidemic.controller;

import com.lintao.epidemic.bean.*;
import com.lintao.epidemic.bean.*;
import com.lintao.epidemic.service.EpidemicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpSession; import java.util.List; @Controller @RequestMapping("/epidemicData") public class EpidemicController { @Autowired private EpidemicService epidemicService; /** * 录入疫情数据 * @param dailyEpidemicInfo * @param model * @param session * @return */ @PostMapping("/ajax/input") @ResponseBody public AjaxResponseInfo inputData(@RequestBody DailyEpidemicInfo dailyEpidemicInfo, Model model, HttpSession session){ AjaxResponseInfo responseInfo = new AjaxResponseInfo(); //从session中获取当前登录系统的用户信息 UserInfo user = (UserInfo)session.getAttribute("loginUser"); if(user==null){ responseInfo.setCode(-2); responseInfo.setMsg("你还没有登录"); }else{ //将数据保存 List<ProvinceInfo> list = epidemicService.saveData(dailyEpidemicInfo,user.getUserId()); responseInfo.setData(list); } return responseInfo; } /** * 查询最新累积疫情信息 * @return */ @GetMapping("/ajax/lastestData") @ResponseBody public AjaxResponseInfo findLastestData(){ AjaxResponseInfo responseInfo = new AjaxResponseInfo(); List<EpidemicDetailInfo> list = epidemicService.findLastestData(); responseInfo.setData(list); return responseInfo; } /** * 查询今日疫情信息 * @return */ @GetMapping("/ajax/todayData") @ResponseBody public AjaxResponseInfo findTodayData(){ AjaxResponseInfo responseInfo = new AjaxResponseInfo(); List<EpidemicInfo> list = epidemicService.findTodayData(); responseInfo.setData(list); return responseInfo; } /** * 查询昨日疫情信息 * @return */ @GetMapping("/ajax/yesterdayData") @ResponseBody public AjaxResponseInfo findYesterdayData(){ AjaxResponseInfo responseInfo = new AjaxResponseInfo(); List<EpidemicInfo> list = epidemicService.findYesterdayData(); responseInfo.setData(list); return responseInfo; } }

service的接口

package com.lintao.epidemic.service;

import com.lintao.epidemic.bean.DailyEpidemicInfo;
import com.lintao.epidemic.bean.EpidemicDetailInfo;
import com.lintao.epidemic.bean.EpidemicInfo;
import com.lintao.epidemic.bean.ProvinceInfo;

import java.util.List; public interface EpidemicService { /** * 保存当日的疫情数据,返回还未录入数据的省份列表 * @param dailyEpidemicInfo * @param userId * @return */ List<ProvinceInfo> saveData(DailyEpidemicInfo dailyEpidemicInfo, Integer userId); /** * 获取最新累积疫情数据 * @return */ List<EpidemicDetailInfo> findLastestData(); /** * 获取今日疫情数据 * @return */ List<EpidemicInfo> findTodayData(); /** * 获取昨日疫情数据 * @return */ List<EpidemicInfo> findYesterdayData(); }

service接口的实现类

package com.lintao.epidemic.service.impl;

import com.lintao.epidemic.bean.DailyEpidemicInfo;
import com.lintao.epidemic.bean.EpidemicDetailInfo;
import com.lintao.epidemic.bean.EpidemicInfo;
import com.lintao.epidemic.bean.ProvinceInfo;
import com.lintao.epidemic.service.EpidemicService; import com.lintao.epidemic.mapper.EpidemicMapper; import com.lintao.epidemic.mapper.ProvinceMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.*; @Service public class EpidemicServiceImpl implements EpidemicService { @Autowired private EpidemicMapper epidemicMapper; @Autowired private ProvinceMapper provinceMapper; /** * 保存当日的疫情数据,返回还未录入数据的省份列表 * @param dailyEpidemicInfo * @param userId * @return */ @Override public List<ProvinceInfo> saveData(DailyEpidemicInfo dailyEpidemicInfo, Integer userId) { //获取当前数据,跟系统时间是一致 Date current = new Date(); //数据的日期 String[] ymd = dailyEpidemicInfo.getDate().split("-");//2020-3-15 short year=0,month=0,day=0; year = Short.parseShort(ymd[0]); month= Short.parseShort(ymd[1]); day = Short.parseShort(ymd[2]); //遍历疫情信息 for(EpidemicInfo epidemicInfo: dailyEpidemicInfo.getArray()){ //设置录入该数据的用户编号  epidemicInfo.setUserId(userId); //设置数据的录入日期  epidemicInfo.setInputDate(current); //设置数据对应的日期  epidemicInfo.setDataYear(year); epidemicInfo.setDataMonth(month); epidemicInfo.setDataDay(day); epidemicMapper.saveInfo(epidemicInfo); } return provinceMapper.findNoDataProvinces(year,month,day); } /** * 获取最新累积疫情数据 * @return */ @Override public List<EpidemicDetailInfo> findLastestData() { //查询每个省份的累计数量和当日新增数量 Calendar calendar = new GregorianCalendar();//这个也是获取当前日期 short year=0,month=0,day=0; year = (short)calendar.get(Calendar.YEAR);//年 month = (short)(calendar.get(Calendar.MONTH)+1);//月份(0-11) day = (short)calendar.get(Calendar.DATE);//日  Map<String,Short> condition = new HashMap<>(); condition.put("year",year); condition.put("month",month); condition.put("day",day); //查询每个省份的累计数量和当日新增量 return epidemicMapper.findLastestData(condition); } /** * 获取今日疫情数据 * @return */ @Override public List<EpidemicInfo> findTodayData() { //查询每个省份的累计数量和当日新增数量 Calendar calendar = new GregorianCalendar();//这个也是获取当前日期 short year=0,month=0,day=0; year = (short)calendar.get(Calendar.YEAR);//年 month = (short)(calendar.get(Calendar.MONTH)+1);//月份(0-11) day = (short)(calendar.get(Calendar.DATE));//日  Map<String,Short> condition = new HashMap<>(); condition.put("year",year); condition.put("month",month); condition.put("day",day); //查询每个省份的累计数量和当日新增量 return epidemicMapper.findTodayData(condition); } /** * 获取昨日疫情数据 * @return */ @Override public List<EpidemicInfo> findYesterdayData() { //查询每个省份的累计数量和当日新增数量 Calendar calendar = new GregorianCalendar();//这个也是获取当前日期 short year=0,month=0,day=0; year = (short)calendar.get(Calendar.YEAR);//年 month = (short)(calendar.get(Calendar.MONTH)+1);//月份(0-11) day = (short)(calendar.get(Calendar.DATE)-1);//日  Map<String,Short> condition = new HashMap<>(); condition.put("year",year); condition.put("month",month); condition.put("day",day); //查询每个省份的累计数量和当日新增量 return epidemicMapper.findYesterdayData(condition); } }
EpidemicMapper,对epidemics数据表进行增删改查
package com.lintao.epidemic.mapper;

import com.lintao.epidemic.bean.EpidemicDetailInfo;
import com.lintao.epidemic.bean.EpidemicInfo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select; import java.util.List; import java.util.Map; @Mapper public interface EpidemicMapper { /** * 保存疫情记录 * @param epidemicInfo * @return */ @Insert(value="INSERT INTO epidemics(province_id,data_year,data_month,data_day,affirmed,suspected," + "isolated,dead,cured,user_id,input_date) VALUES(#{provinceId},#{dataYear},#{dataMonth}," + "#{dataDay},#{affirmed},#{suspected},#{isolated},#{dead},#{cured},#{userId},#{inputDate})") int saveInfo(EpidemicInfo epidemicInfo); /** * 根据日期查询累积疫情记录 * @param condition * @return */ @Select(value="SELECT e1.province_id,temp.province_name,e1.data_year,e1.data_month,e1.data_day," + " temp.affirmed_total,temp.suspected_total,temp.isolated_total,temp.cured_total,temp.dead_total" + " FROM epidemics e1 RIGHT OUTER JOIN(" + " SELECT e. province_id,p.province_name,SUM(e.affirmed) affirmed_total," + " SUM(e.suspected) suspected_total,SUM(e.isolated) isolated_total," + " SUM(e.cured) cured_total,SUM(e.dead) dead_total" + " FROM epidemics e RIGHT OUTER JOIN provinces p ON e.province_id = p.province_id" + " GROUP BY e.province_id,p.province_name" + " ) temp ON e1.province_id = temp.province_id" + " WHERE e1.data_year=#{year} AND e1.data_month =#{month} AND e1.data_day =#{day}") List<EpidemicDetailInfo> findLastestData(Map<String, Short> condition); /** * 查询今日疫情信息 * @param condition * @return */ @Select(value="select affirmed,suspected,isolated from epidemics where data_year=#{year} and data_month=#{month} and data_day=#{day} order by province_id") List<EpidemicInfo> findTodayData(Map<String, Short> condition); /** * 查询昨日疫情信息 * @param condition * @return */ @Select(value="select affirmed,suspected,isolated from epidemics where data_year=#{year} and data_month=#{month} and data_day=#{day} order by province_id") List<EpidemicInfo> findYesterdayData(Map<String, Short> condition); }

三、地图和图表的绘制

我的地图和图标都是使用了Echarts,ECharts是一个纯Javascript开发的图表库,利用它可快速开发出商业级数据可视化图表。 官网:https://www.echartsjs.com/zh/index.html 

一、使用方法: 
1、引入 ECharts 文件 <script src="echarts.js"></script> 
2、为 ECharts 准备一个具备高度和宽度的 DOM 容器。 <div id="main" style="width: 600px;height:400px;"></div> 
3、通过 echarts.init() 方法初始化一个 echarts 实例,通过 setOption 方法设置图表的配置项和数据。

// div 节点作为echarts 的渲染容器,基于该div 节点创建一个echarts 实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option = {
title: {
text: '图表的标题'
},
// 提示框
tooltip: {},
// 图例,单击后可隐藏对应的系列
legend: {
data:['图例'] }, // X 轴上的类目名称数组 xAxis: { data: ["类目1","类目2","类目3","类目4","类目5","类目6"] }, // Y 轴 yAxis: {}, //series 值是一个数组。 series: [{ name: '图例', type: 'bar', // 和xAxis.data 定义的类目对应的数值 data: [5, 20, 36, 10, 10, 20] }] }; // 将配置项和数据设置到echarts 实例中,就会显示图表 myChart.setOption(option);

提示: 一个网页中可以创建多个echarts实例,每个 echarts实例独占一个 DOM节点。 每个echarts实例可以在容器中绘制出多个图表。 参数 option 对象包含了针对图表的各种设置,包括:绘制何种图表、图表包含哪些组件、图表使用的数 据等。 
option对象中的 series用来定义图表的类型和数据,其值是个数组,数组中的每个元素对象定义了一个图 表的相关配置。 series.name的值和legend匹配,用来进行图例筛选,因此务必保证两者的名字相同。 series.type的值用来控制图表的类型,取值有:line(折线图)、bar(柱状图)、pie(饼图)、map(地 图)......。 series.data给出了图表所需的数据,根据图表类型的不同数据格式也就不同。

二、柱状图 
2.1 基本参数

var option={
title:{
text:'2020-2-13 广东省一周疫情统计',
subtext:'广东省疾控中心'
},
legend: {
data:["人数"]
},
// 直角坐标系底板
grid: {
//是否显示网格
show:true|false, backgroundColor:'', borderColor:"" }, tooltip: { //触发类型 trigger:'item'|'axis'|'none' }, xAxis: { type: 'category', //可取值:"value" ,"catetory", "time"等。vaue 表示该轴为数值轴,catetory 表示该轴为离散的类目轴,通常x 轴为category,y 轴默认为value,type 为category 时,data 给出类目数据 data:['2-10','2-11','2-12','2-13','2-14','2-15','2-17'] }, yAxis: { // 最大刻度值 max:80 }, series: [{ type: 'bar', name:'人数', data: [10,13,16,18,20,22,23] }] };

2.2 两列对比柱状图 

var option = {
title: {
text: '2-13 日疫情动态',
subtext: "广东省"
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['昨日', '今日']
},
xAxis: {
data: ["确诊", "疑似", "死亡", "治愈", "隔离观察"] }, yAxis: {}, series: [{ name: '昨日', type: 'bar', data: [5, 20, 6, 10, 10] }, { name: '今日', type: 'bar', data: [15, 10, 16, 12, 18] }] };

2.3 通过AJAX异步加载数据:
通过jQuery异步获取数据后调用myChart.setOption() 传入数据和配置项即可。

// 先设置标题,图例和空的坐标轴
myChart.setOption({
title: {
text: '本日疫情数据'
},
tooltip: {},
legend: {
data:['人数统计']
},
xAxis: {
data: []
},
yAxis: {},
series: [{
name: '人数统计',
type: 'bar',
data: []
}]
});
// 异步获取x轴的类目及数据后,然后设置到图表中
myChart.setOption({ xAxis: { data: data.categories }, series: [{ name: '人数统计', data: data.data }] });

服务器端的Bean可以设计为:

class AjaxRespInfo{
// 类目列表
private List<String> categories;
// 数值列表
private List<Integer> data;
}

两列对比,则类设计如下:

class AjaxRespInfo{
// 类目列表, ["确诊", "疑似", "死亡", "治愈", "隔离"]
private List<String> categories;
// 昨日数值列表
private List<Integer> yesterday;
// 今日数值列表
private List<Integer> today;
}
// 异步获取类目名称及数据后,设置到图表中
myChart.setOption({
xAxis: {
data: data.categories
},
series: [{
name: '昨日', data: data.yesterday }, { name: '今日', data: data.today }] });

三、折线图
3.1 单图例折线

var option = {
title: {
text: "广东省17 日~21 日新增确诊人数变化"
},
legend: {
data: ["确诊"]
},
xAxis: {
type: 'category',
data: ['17 日', '18 日', '19 日', '20 日', '21 日', '22 日', '23 日']
},
yAxis: {
type: 'value' }, series: [{ name: '确诊', data: [3, 8, 0, 7, 12, 10, 5], type: 'line' }] };

3.2 多折线图

var option = {
title: {
text: "广东省17 日~21 日患者人数变化"
},
legend: {
data: ["确诊", "疑似"]
},
xAxis: {
type: 'category',
data: ['17 日', '18 日', '19 日', '20 日', '21 日', '22 日', '23 日']
},
yAxis: {
type: 'value' }, series: [{ name: '确诊', data: [3, 8, 0, 7, 12, 10, 5], type: 'line' }, { name: '疑似', data: [34, 28, 30, 17, 22, 15, 35], type: 'line' }] };

四、地图
4.1 基本使用:

<script src="echarts.js"></script>
<script src="map/js/china.js"></script>
var myChart = echarts.init(document.getElementById("main"));
var option = {
title: {
text: "2020-02-02 全国疫情统计"
},
legend:{
data:["确诊人数"]
},
tooltip: {},
visualMap: {
type: 'piecewise', // 分段型视觉映射
min: 0,
max: 1000, splitNumber: 5, //分为5个段 textStyle: { color: 'orange' //文本颜色 } }, series: [{ name: "确诊人数", type: "map", mapType: "china", data: [ {name: '北京', value: 120}, {name: '天津', value: 34}, {name: '上海', value: 206}, {name: '重庆', value: 210}, {name: '河北', value: 27}, {name: '河南', value: 2322}, {name: '云南', value: 7}, {name: '辽宁', value: 9}, {name: '黑龙江', value: 308}, {name: '湖南', value: 174}, {name: '安徽', value: 40}, {name: '山东', value: 26}, {name: '新疆', value: 2}, {name: '江苏', value: 54}, {name: '浙江', value: 943}, {name: '江西', value: 11}, {name: '湖北', value: 8421}, {name: '广西', value: 5}, {name: '甘肃', value: 2}, {name: '山西', value: 4}, {name: '内蒙古', value: 2}, {name: '陕西', value: 133}, {name: '吉林', value: 41}, {name: '福建', value: 21}, {name: '贵州', value: 7}, {name: '广东', value: 122}, {name: '青海', value: 3}, {name: '西藏', value: 0}, {name: '四川', value: 48}, {name: '宁夏', value: 2}, {name: '海南', value: 0}, {name: '台湾', value: 13}, {name: '香港', value: 67}, {name: '澳门', value: 3} ] }] }; myChart.setOption(option);

注意:
1、如果china.js文件有问题造成地图不能正常显示,替换为china.json,代码如下:

$.getJSON("js/china.json", null, function (chinaJson) {
echarts.registerMap('china', chinaJson);
var myChart = echarts.init($("#div1").get(0));
var option = {
title: {
text: ""
},
legend: {
data: [""] }, tooltip: {}, visualMap: { type: 'piecewise', min: 0, max: 10000, splitList: [{ start: 1000, end: 10000 }, { start: 500, end: 1000 }, { start: 100, end: 500 }, { start: 0, end: 100 }], textStyle: { color: 'orange' } }, series: [{ name: "疫情", type: "map", mapType: "china", data: [ {name: '北京', value: 120}, {name: '天津', value: 34}, {name: '上海', value: 206} ] }] }; myChart.setOption(option); }, "json");

2、visualMap.splitNumber表示要划分为几个段,ECharts会自动根据取值范围均匀分段。
也可替换为使用splitList属性指定分段的值范围,如下:

splitList: [{
start: 1000,
end: 10000
}, {
start: 500,
end: 1000
}, {
start: 100, end: 500 }, { start: 0, end: 100 }],

3、连续型视觉映射:

visualMap: {
type: 'continuous',
min: 0,
max: 500,
left: 'left',
top: 'bottom', text: ['高', '低'] // 两端的文本 }

猜你喜欢

转载自www.cnblogs.com/zenglintao/p/12889694.html