Java报表案例

wen java案例 1

本文目录导读:

Java报表案例

  1. 项目结构
  2. 核心代码实现
  3. 数据库表结构
  4. 配置文件
  5. 前端页面示例
  6. pom.xml依赖

我来为您提供一个完整的Java报表系统案例,使用Spring Boot + MyBatis + Apache POI/JasperReports实现。

项目结构

src/main/java/com/example/report/
├── controller/
│   └── ReportController.java
├── service/
│   ├── ReportService.java
│   └── impl/
│       └── ReportServiceImpl.java
├── mapper/
│   ├── OrderMapper.java
│   └── UserMapper.java
├── entity/
│   ├── Order.java
│   └── User.java
├── utils/
│   └── ExcelExportUtil.java
└── ReportApplication.java
src/main/resources/
├── mapper/
│   ├── OrderMapper.xml
│   └── UserMapper.xml
└── templates/
    └── report.jrxml

核心代码实现

实体类

// Order.java
package com.example.report.entity;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class Order {
    private Long id;
    private String orderNo;
    private String customerName;
    private BigDecimal amount;
    private Integer status;
    private Date createTime;
    private String statusDesc;
}
// User.java
package com.example.report.entity;
import lombok.Data;
import java.util.Date;
@Data
public class User {
    private Long id;
    private String username;
    private String email;
    private String phone;
    private Date createTime;
    private Integer userStatus;
}

Mapper接口

// OrderMapper.java
package com.example.report.mapper;
import com.example.report.entity.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
@Mapper
public interface OrderMapper {
    List<Order> getOrderReport(@Param("startDate") String startDate, 
                               @Param("endDate") String endDate,
                               @Param("status") Integer status);
    List<Map<String, Object>> getOrderStatistics(@Param("startDate") String startDate, 
                                                @Param("endDate") String endDate);
}
// UserMapper.java
package com.example.report.mapper;
import com.example.report.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface UserMapper {
    List<User> getUserReport(@Param("startDate") String startDate, 
                            @Param("endDate") String endDate);
}

Mapper XML

<!-- OrderMapper.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">
<mapper namespace="com.example.report.mapper.OrderMapper">
    <select id="getOrderReport" resultType="com.example.report.entity.Order">
        SELECT 
            o.id,
            o.order_no AS orderNo,
            o.customer_name AS customerName,
            o.amount,
            o.status,
            o.create_time AS createTime,
            CASE o.status
                WHEN 1 THEN '待付款'
                WHEN 2 THEN '已付款'
                WHEN 3 THEN '已完成'
                WHEN 4 THEN '已取消'
                ELSE '未知状态'
            END AS statusDesc
        FROM orders o
        <where>
            <if test="startDate != null and startDate != ''">
                AND o.create_time &gt;= #{startDate}
            </if>
            <if test="endDate != null and endDate != ''">
                AND o.create_time &lt;= #{endDate}
            </if>
            <if test="status != null">
                AND o.status = #{status}
            </if>
        </where>
        ORDER BY o.create_time DESC
    </select>
    <select id="getOrderStatistics" resultType="java.util.Map">
        SELECT 
            DATE(create_time) AS date,
            COUNT(*) AS orderCount,
            COALESCE(SUM(amount), 0) AS totalAmount,
            AVG(amount) AS avgAmount
        FROM orders
        <where>
            <if test="startDate != null and startDate != ''">
                AND create_time &gt;= #{startDate}
            </if>
            <if test="endDate != null and endDate != ''">
                AND create_time &lt;= #{endDate}
            </if>
        </where>
        GROUP BY DATE(create_time)
        ORDER BY date DESC
    </select>
</mapper>
<!-- UserMapper.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">
<mapper namespace="com.example.report.mapper.UserMapper">
    <select id="getUserReport" resultType="com.example.report.entity.User">
        SELECT 
            u.id,
            u.username,
            u.email,
            u.phone,
            u.create_time AS createTime,
            u.user_status AS userStatus
        FROM users u
        <where>
            <if test="startDate != null and startDate != ''">
                AND u.create_time &gt;= #{startDate}
            </if>
            <if test="endDate != null and endDate != ''">
                AND u.create_time &lt;= #{endDate}
            </if>
        </where>
        ORDER BY u.create_time DESC
    </select>
</mapper>

Service层

// ReportService.java
package com.example.report.service;
import com.example.report.entity.Order;
import com.example.report.entity.User;
import java.util.List;
import java.util.Map;
public interface ReportService {
    List<Order> getOrderReport(String startDate, String endDate, Integer status);
    List<User> getUserReport(String startDate, String endDate);
    List<Map<String, Object>> getOrderStatistics(String startDate, String endDate);
    byte[] exportOrderReportExcel(String startDate, String endDate, Integer status);
    byte[] exportUserReportExcel(String startDate, String endDate);
    byte[] exportOrderReportPDF(String startDate, String endDate, Integer status);
}
// ReportServiceImpl.java
package com.example.report.service.impl;
import com.example.report.entity.Order;
import com.example.report.entity.User;
import com.example.report.mapper.OrderMapper;
import com.example.report.mapper.UserMapper;
import com.example.report.service.ReportService;
import com.example.report.utils.ExcelExportUtil;
import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class ReportServiceImpl implements ReportService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Override
    public List<Order> getOrderReport(String startDate, String endDate, Integer status) {
        return orderMapper.getOrderReport(startDate, endDate, status);
    }
    @Override
    public List<User> getUserReport(String startDate, String endDate) {
        return userMapper.getUserReport(startDate, endDate);
    }
    @Override
    public List<Map<String, Object>> getOrderStatistics(String startDate, String endDate) {
        return orderMapper.getOrderStatistics(startDate, endDate);
    }
    @Override
    public byte[] exportOrderReportExcel(String startDate, String endDate, Integer status) {
        List<Order> orders = getOrderReport(startDate, endDate, status);
        String[] headers = {"订单编号", "客户名称", "订单金额", "订单状态", "创建时间"};
        String[] fields = {"orderNo", "customerName", "amount", "statusDesc", "createTime"};
        return ExcelExportUtil.exportToExcel(headers, fields, orders);
    }
    @Override
    public byte[] exportUserReportExcel(String startDate, String endDate) {
        List<User> users = getUserReport(startDate, endDate);
        String[] headers = {"用户名", "邮箱", "手机号", "注册时间", "状态"};
        String[] fields = {"username", "email", "phone", "createTime", "userStatus"};
        return ExcelExportUtil.exportToExcel(headers, fields, users);
    }
    @Override
    public byte[] exportOrderReportPDF(String startDate, String endDate, Integer status) {
        try {
            List<Order> orders = getOrderReport(startDate, endDate, status);
            // 加载报表模板
            File file = ResourceUtils.getFile("classpath:templates/report.jrxml");
            JasperReport jasperReport = JasperCompileManager.compileReport(file.getAbsolutePath());
            // 准备数据
            JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(orders);
            Map<String, Object> parameters = new HashMap<>();
            parameters.put("startDate", startDate);
            parameters.put("endDate", endDate);
            // 填充数据
            JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource);
            // 导出PDF
            return JasperExportManager.exportReportToPdf(jasperPrint);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("导出PDF失败", e);
        }
    }
}

Excel导出工具类

// ExcelExportUtil.java
package com.example.report.utils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.util.ReflectionUtils;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class ExcelExportUtil {
    public static <T> byte[] exportToExcel(String[] headers, String[] fields, List<T> dataList) {
        try (Workbook workbook = new XSSFWorkbook(); 
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            Sheet sheet = workbook.createSheet("报表数据");
            // 创建表头样式
            CellStyle headerStyle = workbook.createCellStyle();
            Font headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setColor(IndexedColors.WHITE.getIndex());
            headerStyle.setFont(headerFont);
            headerStyle.setFillForegroundColor(IndexedColors.BLUE.getIndex());
            headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);
            // 创建数据样式
            CellStyle dataStyle = workbook.createCellStyle();
            dataStyle.setAlignment(HorizontalAlignment.CENTER);
            // 创建表头行
            Row headerRow = sheet.createRow(0);
            for (int i = 0; i < headers.length; i++) {
                Cell cell = headerRow.createCell(i);
                cell.setCellValue(headers[i]);
                cell.setCellStyle(headerStyle);
                sheet.autoSizeColumn(i);
            }
            // 填充数据
            int rowNum = 1;
            for (T data : dataList) {
                Row row = sheet.createRow(rowNum++);
                for (int col = 0; col < fields.length; col++) {
                    Cell cell = row.createCell(col);
                    Object value = getFieldValue(data, fields[col]);
                    if (value != null) {
                        if (value instanceof Date) {
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            cell.setCellValue(sdf.format(value));
                        } else {
                            cell.setCellValue(value.toString());
                        }
                    } else {
                        cell.setCellValue("");
                    }
                    cell.setCellStyle(dataStyle);
                }
            }
            workbook.write(outputStream);
            return outputStream.toByteArray();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("导出Excel失败", e);
        }
    }
    private static Object getFieldValue(Object data, String fieldName) {
        try {
            Field field = data.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(data);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            return null;
        }
    }
}

Controller

// ReportController.java
package com.example.report.controller;
import com.example.report.entity.Order;
import com.example.report.entity.User;
import com.example.report.service.ReportService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/report")
public class ReportController {
    @Autowired
    private ReportService reportService;
    @GetMapping("/orders")
    public ResponseEntity<ApiResponse<List<Order>>> getOrderReport(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false) Integer status) {
        List<Order> orders = reportService.getOrderReport(startDate, endDate, status);
        return ResponseEntity.ok(ApiResponse.success(orders));
    }
    @GetMapping("/users")
    public ResponseEntity<ApiResponse<List<User>>> getUserReport(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) {
        List<User> users = reportService.getUserReport(startDate, endDate);
        return ResponseEntity.ok(ApiResponse.success(users));
    }
    @GetMapping("/statistics")
    public ResponseEntity<ApiResponse<List<Map<String, Object>>>> getOrderStatistics(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) {
        List<Map<String, Object>> statistics = reportService.getOrderStatistics(startDate, endDate);
        return ResponseEntity.ok(ApiResponse.success(statistics));
    }
    @GetMapping("/export/excel/orders")
    public ResponseEntity<byte[]> exportOrderExcel(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false) Integer status) {
        byte[] data = reportService.exportOrderReportExcel(startDate, endDate, status);
        String filename = "order_report_" + System.currentTimeMillis() + ".xlsx";
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, 
                       "attachment; filename=" + filename)
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .body(data);
    }
    @GetMapping("/export/excel/users")
    public ResponseEntity<byte[]> exportUserExcel(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate) {
        byte[] data = reportService.exportUserReportExcel(startDate, endDate);
        String filename = "user_report_" + System.currentTimeMillis() + ".xlsx";
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, 
                       "attachment; filename=" + filename)
                .contentType(MediaType.parseMediaType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"))
                .body(data);
    }
    @GetMapping("/export/pdf/orders")
    public ResponseEntity<byte[]> exportOrderPDF(
            @RequestParam(required = false) String startDate,
            @RequestParam(required = false) String endDate,
            @RequestParam(required = false) Integer status) {
        byte[] data = reportService.exportOrderReportPDF(startDate, endDate, status);
        String filename = "order_report_" + System.currentTimeMillis() + ".pdf";
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, 
                       "attachment; filename=" + filename)
                .contentType(MediaType.APPLICATION_PDF)
                .body(data);
    }
    // 通用响应类
    public static class ApiResponse<T> {
        private int code;
        private String message;
        private T data;
        public static <T> ApiResponse<T> success(T data) {
            ApiResponse<T> response = new ApiResponse<>();
            response.setCode(200);
            response.setMessage("success");
            response.setData(data);
            return response;
        }
        // getter and setter...
        public int getCode() { return code; }
        public void setCode(int code) { this.code = code; }
        public String getMessage() { return message; }
        public void setMessage(String message) { this.message = message; }
        public T getData() { return data; }
        public void setData(T data) { this.data = data; }
    }
}

主启动类

// ReportApplication.java
package com.example.report;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.example.report.mapper")
public class ReportApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReportApplication.class, args);
    }
}

数据库表结构

-- 订单表
CREATE TABLE orders (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    order_no VARCHAR(50) NOT NULL UNIQUE,
    customer_name VARCHAR(100) NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    status TINYINT NOT NULL DEFAULT 1 COMMENT '1:待付款 2:已付款 3:已完成 4:已取消',
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_create_time (create_time),
    INDEX idx_status (status)
);
-- 用户表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100),
    phone VARCHAR(20),
    user_status TINYINT DEFAULT 1 COMMENT '1:正常 0:禁用',
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
    INDEX idx_create_time (create_time)
);

配置文件

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/report_db?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: yourpassword
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.report.entity
  configuration:
    map-underscore-to-camel-case: true
server:
  port: 8080

前端页面示例

<!-- report.html -->
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">报表系统</title>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
    <script>
        // 获取订单报表
        async function getOrderReport() {
            const startDate = document.getElementById('startDate').value;
            const endDate = document.getElementById('endDate').value;
            const status = document.getElementById('status').value;
            const params = new URLSearchParams();
            if (startDate) params.append('startDate', startDate);
            if (endDate) params.append('endDate', endDate);
            if (status) params.append('status', status);
            const response = await fetch(`/api/report/orders?${params}`);
            const result = await response.json();
            // 渲染表格
            renderOrderTable(result.data);
        }
        // 导出Excel
        function exportExcel() {
            const startDate = document.getElementById('startDate').value;
            const endDate = document.getElementById('endDate').value;
            const status = document.getElementById('status').value;
            let url = '/api/report/export/excel/orders?';
            if (startDate) url += `startDate=${startDate}&`;
            if (endDate) url += `endDate=${endDate}&`;
            if (status) url += `status=${status}`;
            window.open(url, '_blank');
        }
        // 导出PDF
        function exportPDF() {
            const startDate = document.getElementById('startDate').value;
            const endDate = document.getElementById('endDate').value;
            const status = document.getElementById('status').value;
            let url = '/api/report/export/pdf/orders?';
            if (startDate) url += `startDate=${startDate}&`;
            if (endDate) url += `endDate=${endDate}&`;
            if (status) url += `status=${status}`;
            window.open(url, '_blank');
        }
        // 渲染订单统计图表
        async function renderStatisticChart() {
            const startDate = document.getElementById('startDate').value;
            const endDate = document.getElementById('endDate').value;
            const params = new URLSearchParams();
            if (startDate) params.append('startDate', startDate);
            if (endDate) params.append('endDate', endDate);
            const response = await fetch(`/api/report/statistics?${params}`);
            const result = await response.json();
            // 使用ECharts渲染统计图
            const chart = echarts.init(document.getElementById('statisticChart'));
            const dates = result.data.map(item => item.date);
            const amounts = result.data.map(item => item.totalAmount);
            const option = {
                title: { text: '订单金额统计' },
                tooltip: {},
                xAxis: { data: dates },
                yAxis: {},
                series: [{
                    name: '金额',
                    type: 'bar',
                    data: amounts
                }]
            };
            chart.setOption(option);
        }
    </script>
</head>
<body>
    <div>
        <label>开始日期: <input type="date" id="startDate"></label>
        <label>结束日期: <input type="date" id="endDate"></label>
        <label>订单状态: 
            <select id="status">
                <option value="">全部</option>
                <option value="1">待付款</option>
                <option value="2">已付款</option>
                <option value="3">已完成</option>
                <option value="4">已取消</option>
            </select>
        </label>
        <button onclick="getOrderReport()">查询</button>
        <button onclick="exportExcel()">导出Excel</button>
        <button onclick="exportPDF()">导出PDF</button>
    </div>
    <div id="statisticChart" style="width: 600px; height: 400px;"></div>
    <table id="orderTable">
        <thead>
            <tr>
                <th>订单编号</th>
                <th>客户名称</th>
                <th>订单金额</th>
                <th>订单状态</th>
                <th>创建时间</th>
            </tr>
        </thead>
        <tbody></tbody>
    </table>
</body>
</html>

pom.xml依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
    </parent>
    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>
        <!-- Apache POI for Excel -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.2</version>
        </dependency>
        <!-- JasperReports for PDF -->
        <dependency>
            <groupId>net.sf.jasperreports</groupId>
            <artifactId>jasperreports</artifactId>
            <version>6.20.0</version>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

这个完整的报表系统案例包含了:

  1. 数据查询:支持按日期范围、状态等多条件筛选
  2. Excel导出:使用Apache POI实现
  3. PDF导出:使用JasperReports实现
  4. 统计分析:支持订单金额统计、趋势分析
  5. 前端展示:提供查询界面和数据可视化
  6. RESTful API:提供标准化的数据接口

您可以根据实际需求调整报表类型、添加新的报表功能,或者扩展更多数据可视化方式。

上一篇积木报表案例

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!