Spring + ECharts实现数据可视化的案例详解
作者:早起之王
Apache ECharts是一个基于 JavaScript 的开源可视化图表库,在网页上实现数据的可视化,非常好用,本文将通过一个简单的demo来给大家介绍一下Spring + ECharts如何数据可视化,需要的朋友可以参考下
一、成果
做好的demo是这个样子的。
通过下拉框选择查询条件,点击按钮,调用后端接口查询数据,返回前端实现可视化。
二、数据准备
计划做一个学生成绩成绩数据的可视化,用到三张表:
学生表、课程表、成绩表,如下:
三、具体实现
通过上面的成果展示图可以看到,实现了两个需求:
1. 展示某年每个学生各科分数的柱状图
2. 展示近三年某个学生总分的折线图
某年每个学生各科分数的柱状图
后端
1. 按照年份查找所有学生所有科目的分数
2. 把数据处理成ECharts柱状图方便接收的形式,传给前端
3. 把所有年份数据(2021、2022、2023)查询出来,给前端做下拉框的部分
4. 查出学生姓名,给前端做柱状图x轴信息
前端
1. 下拉框选择年份
2. 导入ECharts柱状图,并且填充后端数据
后端代码
ResultJson 规范返回值
@Data public class ResultJson { private Integer code; private String msg; private Object data; public ResultJson(Integer code, String msg, Object data) { this.code = code; this.msg = msg; this.data = data; } public static ResultJson success(Object data){ return success("成功",data); } public static ResultJson success(String msg,Object data){ return new ResultJson(200,msg,data); } }
实体类
@Data @TableName("t_score") public class Score { @TableId(type = IdType.AUTO) private Long id; @TableField private String sno; private String cno; private Integer score; private String year; }
Controller层
@RestController @RequestMapping("score") public class ScoreController { @Autowired ScoreService scoreService; @RequestMapping("listScore") public ResultJson listScore(String year){ return ResultJson.success(scoreService.listScore(year)); } @RequestMapping("listYears") public ResultJson listYears(){ return ResultJson.success(scoreService.listYears()); } }
Service层
public interface ScoreService extends IService<Score> { List<List<Object>> listScore(String year); List<String> listYears(); }
这里是认定了只有数学、英语、语文三门科目的,是写死的写法,可以写成灵活的形式,可以参考后面的需求2。
@Service public class ScoreServiceImpl extends ServiceImpl<ScoreMapper, Score> implements ScoreService { @Autowired ScoreMapper scoreMapper; @Override public List<List<Object>> listScore(String year) { List<StudentScore> studentScores = scoreMapper.listScore(year); List<StudentScore> order = studentScores.stream().sorted(Comparator.comparing(StudentScore::getStudentName) .thenComparing(StudentScore::getCourseName)).collect(Collectors.toList()); TreeMap<String, List<Integer>> treeMap = new TreeMap<>(); for(StudentScore studentScore : order){ String studentName = studentScore.getStudentName(); if(!treeMap.containsKey(studentName)){ treeMap.put(studentName,new ArrayList<>()); } treeMap.get(studentName).add(studentScore.getScore()); } List<List<Object>> lists = new ArrayList<>(); for(int i = 0; i < 4; i++){ lists.add(new ArrayList<>()); } treeMap.forEach((key,value)->{ lists.get(0).add(key); lists.get(1).add(value.get(0)); lists.get(2).add(value.get(1)); lists.get(3).add(value.get(2)); }); return lists; } @Override public List<String> listYears() { return scoreMapper.listYears(); }
Mapper层
@Mapper public interface ScoreMapper extends BaseMapper<Score> { List<StudentScore> listScore(String year); List<String> listYears(); }
ScoreMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace => mapper接口 类的全限定名 --> <mapper namespace="com.zqzw.echart.mapper.ScoreMapper"> <resultMap id="BaseResultMap" type="com.zqzw.echart.entity.StudentScore"> <id column="id" jdbcType="BIGINT" property="id"/> <result column="student_name" jdbcType="VARCHAR" property="studentName"/> <result column="course_name" jdbcType="VARCHAR" property="courseName"/> <result column="score" jdbcType="INTEGER" property="score"/> </resultMap> <select id="listScore" resultMap="BaseResultMap"> select student_name,course_name,score from t_score sc inner join t_student s on sc.sno = s.sno inner join t_course c on sc.cno = c.cno where year = #{year} </select> <select id="listYears" resultType="java.lang.String"> select distinct year from t_score order by year </select> </mapper>
前端代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts-Demo</title> </head> <body> <h1>成绩查询</h1> <div id="main" style="width: 600px;height:400px;" ></div> <select id="year" style = "width: 100px"></select> <button id = "b1" onclick="list();">某年每个学生的各科分数</button> </body> </html> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <script src=" https://cdn.jsdelivr.net/npm/echarts@5.4.2/dist/echarts.min.js "></script> <script > const myChart = echarts.init(document.getElementById('main')); let option = { xAxis: { data: [] }, yAxis: {}, series: [ { type: 'bar', data: [] }, { type: 'bar', data: [] }, { type: 'bar', data: [] } ] }; $(function () { $.ajax({ url:"http://localhost:8080/score/listYears", dataType:"json", data:{}, type:"post", success:function (res) { var obj = document.getElementById("year"); obj.options.add(new Option(res.data[0],res.data[0],true)); for(var i = 1; i < res.data.length; i++){ obj.options.add(new Option(res.data[i],res.data[i])); } } }); }); function list(){ var obj = document.getElementById("year"); var index = obj.selectedIndex; if(index < 0){ index = 0; } var key = obj.options[index].value; $.ajax({ url:"http://localhost:8080/score/listScore", dataType:"json", data:{"year": key}, type:"post", success:function(res){ option.xAxis.data = res.data[0]; option.series[0].data = res.data[1]; option.series[1].data = res.data[2]; option.series[2].data = res.data[3]; myChart.clear(); myChart.setOption(option); }, error:function(){ } }); } </script>
近三年某个学生总分的折线图
后端
1. 按照学号查出每年的总分
2. 把数据处理成ECharts柱状图方便接收的形式,传给前端
3. 把所有学生姓名查询出来,给前端做下拉框的部分
4. 查出年份数据,给前端做柱状图x轴信息
前端
1. 下拉框显示学生姓名,实际值是学号
2. 导入ECharts折线图,并且填充后端数据
四、完整代码
后端代码
加上这个部分就是全部了,所以这里直接放出完整的代码了
ResultJson不变
实体类
@Data @TableName("t_student") public class Student { @TableId(type = IdType.AUTO) private Long id; @TableField private String sno; @TableField("student_name") private String studentName; private Integer sex; }
@Data public class TotalScore extends Score{ private Integer totalScore; }
Controller层
@RestController @RequestMapping("score") public class ScoreController { @Autowired ScoreService scoreService; @RequestMapping("listScore") public ResultJson listScore(String year){ return ResultJson.success(scoreService.listScore(year)); } @RequestMapping("listYears") public ResultJson listYears(){ return ResultJson.success(scoreService.listYears()); } @RequestMapping("listTotal") public ResultJson listTotal(String sno){ return ResultJson.success(scoreService.listTotal(sno)); } @RequestMapping("listStudents") public ResultJson listStudents(){ return ResultJson.success(scoreService.listStudents()); } }
Service层
public interface ScoreService extends IService<Score> { List<List<Object>> listScore(String year); List<String> listYears(); List<List<Object>> listTotal(String sno); List<Student> listStudents(); }
@Service public class ScoreServiceImpl extends ServiceImpl<ScoreMapper, Score> implements ScoreService { @Autowired ScoreMapper scoreMapper; @Override public List<List<Object>> listScore(String year) { List<StudentScore> studentScores = scoreMapper.listScore(year); List<StudentScore> order = studentScores.stream().sorted(Comparator.comparing(StudentScore::getStudentName) .thenComparing(StudentScore::getCourseName)).collect(Collectors.toList()); TreeMap<String, List<Integer>> treeMap = new TreeMap<>(); for(StudentScore studentScore : order){ String studentName = studentScore.getStudentName(); if(!treeMap.containsKey(studentName)){ treeMap.put(studentName,new ArrayList<>()); } treeMap.get(studentName).add(studentScore.getScore()); } List<List<Object>> lists = new ArrayList<>(); for(int i = 0; i < 4; i++){ lists.add(new ArrayList<>()); } treeMap.forEach((key,value)->{ lists.get(0).add(key); lists.get(1).add(value.get(0)); lists.get(2).add(value.get(1)); lists.get(3).add(value.get(2)); }); return lists; } @Override public List<String> listYears() { return scoreMapper.listYears(); } @Override public List<List<Object>> listTotal(String sno) { List<TotalScore> totalScores = scoreMapper.listTotal(sno); List<List<Object>> result = new ArrayList<>(); result.add(new ArrayList<>()); result.add(new ArrayList<>()); for(TotalScore t : totalScores){ result.get(0).add(t.getYear()); result.get(1).add(t.getTotalScore()); } return result; } @Override public List<Student> listStudents() { return scoreMapper.listStudents(); } }
Mapper层
@Mapper public interface ScoreMapper extends BaseMapper<Score> { List<StudentScore> listScore(String year); List<String> listYears(); List<TotalScore> listTotal(String sno); List<Student> listStudents(); }
ScoreMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!--namespace => mapper接口 类的全限定名 --> <mapper namespace="com.zqzw.echart.mapper.ScoreMapper"> <resultMap id="BaseResultMap" type="com.zqzw.echart.entity.StudentScore"> <id column="id" jdbcType="BIGINT" property="id"/> <result column="student_name" jdbcType="VARCHAR" property="studentName"/> <result column="course_name" jdbcType="VARCHAR" property="courseName"/> <result column="score" jdbcType="INTEGER" property="score"/> </resultMap> <select id="listScore" resultMap="BaseResultMap"> select student_name,course_name,score from t_score sc inner join t_student s on sc.sno = s.sno inner join t_course c on sc.cno = c.cno where year = #{year} </select> <select id="listYears" resultType="java.lang.String"> select distinct year from t_score order by year </select> <select id="listTotal" resultType="com.zqzw.echart.entity.TotalScore"> select sum(score) totalScore,year from t_score where sno = #{sno} group by year order by year </select> <select id="listStudents" resultType="com.zqzw.echart.entity.Student"> select student_name,sno from t_student </select> </mapper>
前端代码
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ECharts-Demo</title> </head> <body> <h1>成绩查询</h1> <div id="main" style="width: 600px;height:400px;" ></div> <select id="year" style = "width: 100px"></select> <button id = "b1" onclick="list();">某年每个学生的各科分数</button> <select id="student" style = "width: 100px"></select> <button id = "b2" onclick="listTotal();">某学生三年总分折线图</button> </body> </html> <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <script src=" https://cdn.jsdelivr.net/npm/echarts@5.4.2/dist/echarts.min.js "></script> <script > const myChart = echarts.init(document.getElementById('main')); let option = { xAxis: { data: [] }, yAxis: {}, series: [ { type: 'bar', data: [] }, { type: 'bar', data: [] }, { type: 'bar', data: [] } ] }; let option1 = { xAxis: { type: 'category', data: [] }, yAxis: { type: 'value' }, series: [ { data: [], type: 'line', label: { show: false, position: 'bottom', textStyle: { fontSize: 10 } } } ] }; function initSelect1(){ $.ajax({ url:"http://localhost:8080/score/listStudents", dataType:"json", data:"{}", type:"post", success:function(res){ for(var i = 0; i< res.data.length; i++){ var obj = document.getElementById("student"); obj.options.add(new Option(res.data[i].studentName,res.data[i].sno)); } } }); } initSelect1(); $(function () { $.ajax({ url:"http://localhost:8080/score/listYears", dataType:"json", data:{}, type:"post", success:function (res) { var obj = document.getElementById("year"); obj.options.add(new Option(res.data[0],res.data[0],true)); for(var i = 1; i < res.data.length; i++){ obj.options.add(new Option(res.data[i],res.data[i])); } } }); }); function listTotal() { var obj = document.getElementById("student"); var index = obj.selectedIndex; var key = obj.options[index].value; $.ajax({ url: "http://localhost:8080/score/listTotal", data: {"sno": key}, dataType: "json", type: "post", success: function (res) { option1.xAxis.data = res.data[0]; for (var i = 1; i < res.data.length; i++) { option1.series[i - 1].data = res.data[i]; } myChart.clear(); myChart.setOption(option1); } }); } function list(){ var obj = document.getElementById("year"); var index = obj.selectedIndex; if(index < 0){ index = 0; } var key = obj.options[index].value; $.ajax({ url:"http://localhost:8080/score/listScore", //请求的url地址 dataType:"json", //返回格式为json data:{"year": key}, //参数值 type:"post", //请求方式 success:function(res){ option.xAxis.data = res.data[0]; option.series[0].data = res.data[1]; option.series[1].data = res.data[2]; option.series[2].data = res.data[3]; myChart.clear(); myChart.setOption(option); }, error:function(){ } }); } </script>
以上就是Spring + ECharts实现数据可视化的案例详解的详细内容,更多关于Spring + ECharts数据可视化的资料请关注脚本之家其它相关文章!