Building an Epidemic Data Visualization System with ECharts and JSP

This article describes how to create a web-based epidemic data visualization system that retrieves information from a database and displays it in both tabular and graphical formats. The implementation leverages ECharts for dynamic chart rendering and JSP for the web interface.

Key Implementation Challenges

1. Data Integration with ECharts Dataset

When integrating ECharts visualization, the primary challenge was populating the dataset's source property dynamically. Initially attempted to use JSTL foreach loops for data injection, but encountered technical limitations. The solution involved switching to embedded Java scriptlets within JSP to iterate through request attributes and construct the data array.

2. ECharts Library Integrasion

Downloading and integrating ECharts requires: - Visit the official ECharts website - Right-click on the JS file link and select "Save As" - Store in a dedicated JavaScript directory for organized reference - Include via relative path in your HTML head section

Technical Implementation

Web Interface (Visualization Page)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@page import="com.model.EpidemicData"%>
<%@page import="java.util.List"%>

<html>
<head>
    <meta charset="utf-8">
    <title>Epidemic Data Visualization</title>
    <script src="assets/echarts.min.js"></script>
    <script type="text/javascript" src="assets/jquery-3.6.0.min.js"></script>
</head>
<body>
<%         
request.setCharacterEncoding("UTF-8");
List<EpidemicData> epidemicRecords = (List<EpidemicData>) request.getAttribute("dataList"); 
int recordCounter = 0;
%>

    <!-- Chart container -->
    <div id="chartContainer" style="width: 1200px;height:800px;"></div>
    <script type="text/javascript">
        var epidemicChart = echarts.init(document.getElementById('chartContainer'));
        
        var chartConfig = {
            dataset: {
                source: [
                    ['Region', 'ConfirmedCases'],
                    <%
                    if(epidemicRecords != null){
                        for(EpidemicData record : epidemicRecords){ 
                            recordCounter++;
                    %>
                            [<%=Integer.parseInt(record.getConfirmedCases())%>,'<%=record.getRegionName()%>'],
                    <%
                        if(recordCounter > 33) break;
                        }
                    }
                    %>
                ]
            },
            grid: {containLabel: true},
            xAxis: {},
            yAxis: {type: 'category'},
            
            visualMap: {
                orient: 'horizontal',
                left: 'center',
                min: 10,
                max: 100,
                text: ['High Infection Rate', 'Low Infection Rate'],
                dimension: 0,
                inRange: {
                    color: ['#FFEB3B', '#F44336']
                }
            },
            
            series: [{
                type: 'bar',
                encode: {
                    x: 'Region',
                    y: 'ConfirmedCases'
                }
            }]
        };
        
        epidemicChart.setOption(chartConfig);
    </script>
    
    <!-- Data Table -->
    <div align="center">
        <table border="1" style="width:600px;height:40px;font-size: 20px">
            <tr>
                <td>Region</td>
                <td>City</td>
                <td>Confirmed</td>
                <td>Recovered</td>
                <td>Deceased</td>
            </tr>
            <%
            if(epidemicRecords != null){
                for(EpidemicData record : epidemicRecords){
            %>
            <tr>
                <td><%=record.getRegionName()%></td>
                <td><%=record.getCityName()%></td>
                <td><%=record.getConfirmedCases()%></td>
                <td><%=record.getRecoveredCases()%></td>
                <td><%=record.getDeathCases()%></td>
            </tr>
            <%
                }
            }
            %>
        </table>
    </div>
</body>
</html>

Search Interface

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<html>
<head>
<meta charset="UTF-8">
<title>Epidemic Data Query System</title>
</head>
<body>
<div align="center">
    <section>
        <form action="DataController?action=query" method="post" onsubmit="return validateInput()">
            <span><font size="5" color="black">Query Date:</font></span>
            <input style="width:200px;height: 30px;font-size: 20px" type="text" name="queryDate" id="queryDate">
            <br/>
            <input style="width:80px;height: 40px;font-size: 15px" type="submit" value="Search">
            <br/>
        </form>
    </section>
</div>
</body>
</html>

Data Model Class

package com.model;

public class EpidemicData {
    private String reportDate;
    private String regionName;
    private String cityName;
    private String suspectedCases;
    private String regionCode;
    private String newCases;
    private String confirmedCases;
    private String deathCases;
    private String seriousCases;
    private String recoveredCases;
    private String dataSource;
    
    public EpidemicData(String date, String city, String newConfirmed, 
                       String confirmed, String deaths, String serious, 
                       String recovered, String source) {
        this.reportDate = date;
        this.cityName = city;
        this.newCases = newConfirmed;
        this.confirmedCases = confirmed;
        this.deathCases = deaths;
        this.seriousCases = serious;
        this.recoveredCases = recovered;
        this.dataSource = source;
    }
    
    // Getters and Setters
    public String getReportDate() { return reportDate; }
    public void setReportDate(String reportDate) { this.reportDate = reportDate; }
    
    public String getRegionName() { return regionName; }
    public void setRegionName(String regionName) { this.regionName = regionName; }
    
    public String getCityName() { return cityName; }
    public void setCityName(String cityName) { this.cityName = cityName; }
    
    public String getConfirmedCases() { return confirmedCases; }
    public void setConfirmedCases(String confirmedCases) { this.confirmedCases = confirmedCases; }
    
    public String getRecoveredCases() { return recoveredCases; }
    public void setRecoveredCases(String recoveredCases) { this.recoveredCases = recoveredCases; }
    
    public String getDeathCases() { return deathCases; }
    public void setDeathCases(String deathCases) { this.deathCases = deathCases; }
}

Database Access Layer

package com.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.model.EpidemicData;
import com.util.DatabaseConnection;

public class EpidemicDAO {
    
    public static List<EpidemicData> fetchDataByDate(String searchDate) throws Exception {
        Connection dbConnection = DatabaseConnection.getConnection();
        List<EpidemicData> dataList = new ArrayList<>();
        Statement queryStatement = null;
        
        String sqlQuery = "SELECT * FROM epidemic_data WHERE report_date LIKE '%" + searchDate + "%'";
        
        queryStatement = dbConnection.createStatement();
        ResultSet queryResult = queryStatement.executeQuery(sqlQuery);
        
        while(queryResult.next()) {
            String confirmedCount = queryResult.getString("confirmed_cases");
            String province = queryResult.getString("province_name");
            String city = queryResult.getString("city_name");
            String recovered = queryResult.getString("recovered_cases");
            String deaths = queryResult.getString("death_cases");
            
            EpidemicData record = new EpidemicData(province, confirmedCount, city, recovered, deaths);
            dataList.add(record);
        }
        
        return dataList;
    }
}

Controller Servlet

package com.controller;

import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.model.EpidemicData;
import com.dao.EpidemicDAO;

@WebServlet("/DataController")
public class DataController extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    protected void service(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        String action = request.getParameter("action");
        
        if("query".equals(action)) {
            try {
                performSearch(request, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void performSearch(HttpServletRequest request, HttpServletResponse response) 
            throws Exception {
        request.setCharacterEncoding("UTF-8");
        String searchDate = request.getParameter("queryDate");
        
        List<EpidemicData> results = EpidemicDAO.fetchDataByDate(searchDate);
        request.setAttribute("dataList", results);
        request.getRequestDispatcher("visualization.jsp").forward(request, response);
    }
}

Database Utility Class

package com.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DatabaseConnection {
    private static final String DB_URL = "jdbc:mysql://localhost:3306/epidemic_db?serverTimezone=UTC&characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "admin123";
    
    public static Connection getConnection() {
        Connection conn = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
            System.out.println("Database connection established successfully!");
        } catch (ClassNotFoundException e) {
            System.err.println("Database driver not found: " + e.getMessage());
        } catch (SQLException e) {
            System.err.println("Connection failed: " + e.getMessage());
        }
        return conn;
    }
    
    public static void closeResources(ResultSet rs, Statement stmt, Connection conn) {
        try {
            if (rs != null) rs.close();
            if (stmt != null) stmt.close();
            if (conn != null) conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

Tags: echarts JSP java MySQL Data Visualization

Posted on Mon, 08 Jun 2026 18:20:26 +0000 by khjart