SSM框架篮球运动员大数据可视化分析系统



目录
0、效果展示
1、概述
随着大数据技术和体育科技的快速发展,篮球运动员的数据分析变得越来越重要。通过对篮球运动员的各项数据进行深入分析,可以帮助教练和球队更好地了解球员的表现,制定科学的训练计划和比赛策略。然而,现有的数据分析系统往往存在以下问题:
数据分散:数据来源多样,缺乏统一的管理平台。
分析工具落后:传统的数据分析方法效率低下,无法满足实时分析的需求。
可视化效果差:现有的可视化工具不够直观,难以快速理解数据背后的含义。
用户体验不佳:界面设计不够友好,操作复杂,导致用户使用不便。
开发一个基于SSM框架的篮球运动员大数据可视化分析系统,可以有效解决这些问题,提升数据分析的效率和准确性。
随着云计算、大数据、人工智能等技术的发展,数据分析系统的技术水平也在不断提升。Spring、Spring MVC 和 MyBatis 等开源框架的广泛应用,使得开发高效、稳定的系统成为可能。此外,前端技术(如Vue.js)的进步也为用户提供了更好的交互体验。
Spring Boot:提供了快速搭建微服务应用的能力,简化了开发过程。
Spring MVC:提供了强大的Web应用开发框架,支持MVC模式。
MyBatis:提供了高效的持久层框架,方便进行数据库操作。
Vue.js:提供了现代化的前端框架,支持响应式布局和组件化开发。
ECharts:提供了丰富的图表库,支持多种数据可视化方式。
这些技术的结合使得开发一个高性能、高可用性的篮球运动员大数据可视化分析系统成为可能。
2、搭建环境
本文以实现一个体育运动项目大数据可视化分析系统为目标,从环境搭建到编码实现全过程讲述
我们使用javaweb、J2EE来构建体育运动项目大数据可视化分析系统,环境使用最新版jdk和tomcat,配合mysql数据库
开发工具使用idea(也可以使用eclipse),数据库管理工具使用Navicat Premium
开发框架使用JavaBean Servlet MVC结构;
没有使用SSH(Struts+Spring+Hibernate)或SSM(Spring+SpringMVC+MyBatis),这两个框架我们在别的项目中再介绍开发过程
在项目中会引入My97DatePicker作为前端日期时间选择工具,使用fckeditor作为富媒体编辑器(也可以使用百度的ueditor)
使用DWR(Direct Web Remoting)用于改善web页面与Java类交互,实现远程服务器端AJAX读取登录数据。
使用JSTL(Java server pages standarded tag library,即JSP标准标签库),此库是由JCP(Java community Proces)所制定的标准规范,它主要提供给Java Web开发人员一个标准通用的标签库,并由Apache的Jakarta小组来维护。开发人员可以利用这些标签取代JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。
echarts百度图表插件
3、数据表结构
5 | t_guojia 国家 表 | ||
字段名称 | 自动增长 | 字段类型 | 说明 |
id | - | int | 编号 |
name | - | varchar | 名称 |
jieshao | - | varchar | 描述 |
del | - | varchar | 是否删除 |
6 | t_qiuyuan 球员 表 | ||
字段名称 | 自动增长 | 字段类型 | 说明 |
id | - | int | 编号 |
code | - | varchar | 编号 |
name1 | - | varchar | 名称 |
sex | - | varchar | 性别 |
age | - | varchar | 年龄 |
qiudui_id | - | varchar | 球队ID |
indate | - | varchar | 时间 |
del | - | varchar | 是否删除 |
4、后端代码示例
package com.action;
import java.io.IOException;
import java.sql.ResultSet;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.directwebremoting.WebContext;
import org.directwebremoting.WebContextFactory;
import com.dao.DB;
import com.orm.TAdmin;
import com.orm.TTongji;
import com.orm.Tgrades;
import com.service.liuService;
public class tongji_servlet extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
String type = req.getParameter("type");
if (type.endsWith("tongjiOne")) {
tongjiOne(req, res);
}
if (type.endsWith("tongjiMore")) {
tongjiMore(req, res);
}
}
// 单场比赛统计
public void tongjiOne(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
String bisaidateinfo = "";
bisaidateinfo = req.getParameter("bisaidateinfo");
String wheresql = "";
String qiyuanList = "";
List gradesList = new ArrayList();
List chuanqiuList = new ArrayList();
List zhugongList = new ArrayList();
List shemenList = new ArrayList();
List guorenList = new ArrayList();
List shiwuList = new ArrayList();
List qiangduanList = new ArrayList();
List lanjieList = new ArrayList();
List yueweiList = new ArrayList();
List fanguiList = new ArrayList();
List juliList = new ArrayList();
if (bisaidateinfo != null) {
wheresql = " where bisaidate like '%" + bisaidateinfo + "%'";
String sql = "SELECT name1,code, qiuyuan_id,bisaidate,grades, chuanqiu, zhugong, shemen, guoren, shiwu, qiangduan, lanjie, yuewei, fangui, juli "
+ " FROM `t_grades` " + " left join t_qiuyuan on t_qiuyuan.id=t_grades.qiuyuan_id" + wheresql
+ " group by bisaidate,qiuyuan_id";
Object[] params = {};
DB mydb = new DB();
try {
mydb.doPstm(sql, params);
ResultSet rs = mydb.getRs();
while (rs.next()) {
qiyuanList += "\"" + rs.getString("name1") + "\"" + ",";
gradesList.add(rs.getString("grades"));
chuanqiuList.add(rs.getString("chuanqiu"));
zhugongList.add(rs.getString("zhugong"));
shemenList.add(rs.getString("shemen"));
guorenList.add(rs.getString("guoren"));
shiwuList.add(rs.getString("shiwu"));
qiangduanList.add(rs.getString("qiangduan"));
lanjieList.add(rs.getString("lanjie"));
yueweiList.add(rs.getString("yuewei"));
fanguiList.add(rs.getString("fangui"));
juliList.add(rs.getString("juli"));
}
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
mydb.closed();
}
if (qiyuanList != "") {
qiyuanList = qiyuanList.substring(0, qiyuanList.length() - 1);// 删除多余的逗号
req.setAttribute("bisaidateinfo", bisaidateinfo);
req.setAttribute("qiyuanList", "[" + qiyuanList + "]");
req.setAttribute("gradesList", "[" + listToString(gradesList) + "]");
req.setAttribute("chuanqiuList", "[" + listToString(chuanqiuList) + "]");
req.setAttribute("zhugongList", "[" + listToString(zhugongList) + "]");
req.setAttribute("shemenList", "[" + listToString(shemenList) + "]");
req.setAttribute("guorenList", "[" + listToString(guorenList) + "]");
req.setAttribute("shiwuList", "[" + listToString(shiwuList) + "]");
req.setAttribute("qiangduanList", "[" + listToString(qiangduanList) + "]");
req.setAttribute("lanjieList", "[" + listToString(lanjieList) + "]");
req.setAttribute("yueweiList", "[" + listToString(yueweiList) + "]");
req.setAttribute("fanguiList", "[" + listToString(fanguiList) + "]");
req.setAttribute("juliList", "[" + listToString(juliList) + "]");
} else {
req.setAttribute("bisaidateinfo", "");
req.setAttribute("qiyuanList", "[]");
req.setAttribute("gradesList", "[]");
req.setAttribute("chuanqiuList", "[]");
req.setAttribute("zhugongList", "[]");
req.setAttribute("shemenList", "[]");
req.setAttribute("guorenList", "[]");
req.setAttribute("shiwuList", "[]");
req.setAttribute("qiangduanList", "[]");
req.setAttribute("lanjieList", "[]");
req.setAttribute("yueweiList", "[]");
req.setAttribute("fanguiList", "[]");
req.setAttribute("juliList", "[]");
}
// 获取比赛日期
List bisaiDateList = new ArrayList();
String sql1 = "SELECT bisaidate FROM `t_grades` group by bisaidate ";
Object[] params1 = {};
DB mydb1 = new DB();
try {
mydb1.doPstm(sql1, params1);
ResultSet rs1 = mydb1.getRs();
while (rs1.next()) {
bisaiDateList.add(rs1.getString("bisaidate"));
}
rs1.close();
} catch (Exception e) {
e.printStackTrace();
}
mydb1.closed();
// String ddddd=listToString(qiyuanList);
// System.out.println(ddddd);
req.setAttribute("bisaiDateList", bisaiDateList);
req.getRequestDispatcher("admin/tongji/tongjiOne.jsp").forward(req, res);
}
//多 场比赛统计
public void tongjiMore(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
String bisaidateinfo1 = "";
String bisaidateinfo2 = "";
bisaidateinfo1 = req.getParameter("bisaidateinfo1");
bisaidateinfo2 = req.getParameter("bisaidateinfo2");
String wheresql = "";
String qiyuanList = "";
List gradesList = new ArrayList();
List chuanqiuList = new ArrayList();
List zhugongList = new ArrayList();
List shemenList = new ArrayList();
List guorenList = new ArrayList();
List shiwuList = new ArrayList();
List qiangduanList = new ArrayList();
List lanjieList = new ArrayList();
List yueweiList = new ArrayList();
List fanguiList = new ArrayList();
List juliList = new ArrayList();
List shoufaList = new ArrayList();
if (bisaidateinfo1 != "" && bisaidateinfo2 != "") {
wheresql = " where bisaidate >'"+bisaidateinfo1+"' and bisaidate <'"+bisaidateinfo2+"' ";
String sql = " SELECT name1,code, qiuyuan_id,bisaidate,"
+ " sum(grades) as grades ,sum( chuanqiu) as chuanqiu, sum(zhugong) as zhugong, sum(shemen) as shemen, sum(guoren) as guoren , sum(shiwu) as shiwu, "
+ " sum( qiangduan) as qiangduan, sum(lanjie) as lanjie, sum(yuewei) as yuewei, sum(fangui) as fangui, sum(juli) as juli "
+ " , sum( if( shoufa > 0, shoufa, 0)) as shoufa "
+ " FROM `t_grades` left join t_qiuyuan on t_qiuyuan.id=t_grades.qiuyuan_id " + wheresql
+ " group by qiuyuan_id";
Object[] params = {};
DB mydb = new DB();
try {
mydb.doPstm(sql, params);
ResultSet rs = mydb.getRs();
while (rs.next()) {
qiyuanList += "\"" + rs.getString("name1") + "\"" + ",";
gradesList.add(rs.getString("grades"));
chuanqiuList.add(rs.getString("chuanqiu"));
zhugongList.add(rs.getString("zhugong"));
shemenList.add(rs.getString("shemen"));
guorenList.add(rs.getString("guoren"));
shiwuList.add(rs.getString("shiwu"));
qiangduanList.add(rs.getString("qiangduan"));
lanjieList.add(rs.getString("lanjie"));
yueweiList.add(rs.getString("yuewei"));
fanguiList.add(rs.getString("fangui"));
juliList.add(rs.getString("juli"));
shoufaList.add(rs.getString("shoufa"));
}
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
mydb.closed();
}
if (qiyuanList != "") {
qiyuanList = qiyuanList.substring(0, qiyuanList.length() - 1);// 删除多余的逗号
req.setAttribute("bisaidateinfo", bisaidateinfo1 +"到"+ bisaidateinfo2);
req.setAttribute("qiyuanList", "[" + qiyuanList + "]");
req.setAttribute("gradesList", "[" + listToString(gradesList) + "]");
req.setAttribute("chuanqiuList", "[" + listToString(chuanqiuList) + "]");
req.setAttribute("zhugongList", "[" + listToString(zhugongList) + "]");
req.setAttribute("shemenList", "[" + listToString(shemenList) + "]");
req.setAttribute("guorenList", "[" + listToString(guorenList) + "]");
req.setAttribute("shiwuList", "[" + listToString(shiwuList) + "]");
req.setAttribute("qiangduanList", "[" + listToString(qiangduanList) + "]");
req.setAttribute("lanjieList", "[" + listToString(lanjieList) + "]");
req.setAttribute("yueweiList", "[" + listToString(yueweiList) + "]");
req.setAttribute("fanguiList", "[" + listToString(fanguiList) + "]");
req.setAttribute("juliList", "[" + listToString(juliList) + "]");
req.setAttribute("shoufaList", "[" + listToString(shoufaList) + "]");
} else {
req.setAttribute("bisaidateinfo", "");
req.setAttribute("qiyuanList", "[]");
req.setAttribute("gradesList", "[]");
req.setAttribute("chuanqiuList", "[]");
req.setAttribute("zhugongList", "[]");
req.setAttribute("shemenList", "[]");
req.setAttribute("guorenList", "[]");
req.setAttribute("shiwuList", "[]");
req.setAttribute("qiangduanList", "[]");
req.setAttribute("lanjieList", "[]");
req.setAttribute("yueweiList", "[]");
req.setAttribute("fanguiList", "[]");
req.setAttribute("juliList", "[]");
req.setAttribute("shoufaList", "[]");
}
// 获取比赛日期
List bisaiDateList = new ArrayList();
String sql1 = "SELECT bisaidate FROM `t_grades` group by bisaidate ";
Object[] params1 = {};
DB mydb1 = new DB();
try {
mydb1.doPstm(sql1, params1);
ResultSet rs1 = mydb1.getRs();
while (rs1.next()) {
bisaiDateList.add(rs1.getString("bisaidate"));
}
rs1.close();
} catch (Exception e) {
e.printStackTrace();
}
mydb1.closed();
// String ddddd=listToString(qiyuanList);
// System.out.println(ddddd);
req.setAttribute("bisaiDateList", bisaiDateList);
req.getRequestDispatcher("admin/tongji/tongjiMore.jsp").forward(req, res);
}
// list使用逗号分切
public static String listToString(List<String> stringList) {
if (stringList == null) {
return null;
}
StringBuilder result = new StringBuilder();
boolean flag = false;
for (String string : stringList) {
if (flag) {
result.append(",");
} else {
flag = true;
}
result.append(string);
}
return result.toString();
}
public void dispatch(String targetURI, HttpServletRequest request, HttpServletResponse response) {
RequestDispatcher dispatch = getServletContext().getRequestDispatcher(targetURI);
try {
dispatch.forward(request, response);
return;
} catch (ServletException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void init(ServletConfig config) throws ServletException {
super.init(config);
}
public void destroy() {
}
}
5、前端代码示例
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ page isELIgnored="false"%>
<%
String path = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="pragma" content="no-cache" />
<meta http-equiv="cache-control" content="no-cache" />
<meta http-equiv="expires" content="0" />
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3" />
<meta http-equiv="description" content="This is my page" />
<script type="text/javascript"
src="<%=path%>/My97DatePicker/WdatePicker.js"></script>
<script src="<%=path%>/js/echarts.common.min.js"></script>
<link rel="stylesheet" type="text/css" href="<%=path%>/css/base.css" />
<script type="text/javascript" src="<%=path %>/My97DatePicker/WdatePicker.js"></script>
</head>
<body leftmargin="2" topmargin="2"
background='<%=path%>/images/allbg.gif'>
<form action="<%=path%>/tongji?type=tongjiMore" name="formAdd"
method="post">
赛季比赛日期范围:
开始<input name="bisaidateinfo1" readonly="readonly" class="Wdate" type="text" onfocus="WdatePicker({skin:'whyGreen',dateFmt:'yyyy-MM-dd'})"/>
结束<input name="bisaidateinfo2" readonly="readonly" class="Wdate" type="text" onfocus="WdatePicker({skin:'whyGreen',dateFmt:'yyyy-MM-dd'})"/>
<input type="submit"
value="分析" />
</form>
<div id="main" style="width:98%;height:400px;"></div>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var myChart2 = echarts.init(document.getElementById('main'));
option2 = {
title : {
text : " 赛季数据图"
},
tooltip : {
trigger : 'axis',
axisPointer : {
type : 'cross',
crossStyle : {
color : '#999'
}
},
textStyle : {
align : 'right'
}
},
toolbox : {
feature : {
dataView : {
show : true,
readOnly : false
},
magicType : {
show : true,
type : [ 'line', 'bar' ]
},
restore : {
show : true
},
saveAsImage : {
show : true
}
}
},
legend : {
data : [ '进球','传球','助攻','射门','过人','失误','抢断','拦截','越位','犯规','跑动','首发' ]
},
yAxis : [
{
type : 'value',
name : '次数',
axisLabel : {
formatter : '{value} '
}
}
],
xAxis : [
{
type : 'category',
axisPointer : {
type : 'shadow'
}
}
],
series : [
{
name : '进球',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '传球',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '助攻',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '射门',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '过人',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '失误',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '抢断',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '拦截',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},{
name : '越位',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '犯规',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '跑动',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
},
{
name : '首发',
type : 'bar',
itemStyle : {
normal : {
barBorderRadius : 5
}
},
label : {
/*每个柱子上面是有数字显示的,而且数字是有千分位符号的:*/
normal : {
show : true,
position : 'top'
}
},
markLine : {
symbol : 'none',
data : [
{
type : 'average',
name : '平均值'
}
]
}
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart2.setOption(option2);
myChart2.setOption({
title: {text: '${requestScope.bisaidateinfo} 赛季数据分析'},
xAxis : [
{
data : ${requestScope.qiyuanList}
}
],
series : [
{
data : ${requestScope.gradesList}
},
{
data : ${requestScope.chuanqiuList}
},
{
data : ${requestScope.zhugongList}
},
{
data : ${requestScope.shemenList}
},
{
data : ${requestScope.guorenList}
},
{
data : ${requestScope.shiwuList}
},
{
data : ${requestScope.qiangduanList}
},
{
data : ${requestScope.lanjieList}
},
{
data : ${requestScope.yueweiList}
},
{
data : ${requestScope.fanguiList}
},
{
data : ${requestScope.juliList}
},
{
data : ${requestScope.shoufaList}
}
]
});
</script>
</body>
</html>