本文目录导读:

我将为您提供一个完整的Spring Boot导入导出案例,涵盖Excel文件的导入和导出功能。
项目依赖配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>import-export-demo</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.14</version>
<relativePath/>
</parent>
<properties>
<java.version>1.8</java.version>
<easyexcel.version>3.3.2</easyexcel.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>${easyexcel.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
实体类
package com.example.demo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("user_info")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private String username;
private String email;
private String phone;
private Integer age;
private String address;
private String status;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}
Excel导入导出DTO
package com.example.demo.model;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.alibaba.excel.annotation.write.style.ContentRowHeight;
import com.alibaba.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.time.LocalDateTime;
@Data
@ContentRowHeight(20)
@HeadRowHeight(25)
@ColumnWidth(20)
public class UserExcelDTO {
@ExcelProperty(value = "用户ID", index = 0)
private Long id;
@ExcelProperty(value = "姓名", index = 1)
@NotBlank(message = "姓名不能为空")
private String name;
@ExcelProperty(value = "用户名", index = 2)
@NotBlank(message = "用户名不能为空")
private String username;
@ExcelProperty(value = "邮箱", index = 3)
@Email(message = "邮箱格式不正确")
private String email;
@ExcelProperty(value = "手机号", index = 4)
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@ExcelProperty(value = "年龄", index = 5)
private Integer age;
@ExcelProperty(value = "地址", index = 6)
private String address;
@ExcelProperty(value = "状态", index = 7)
private String status;
@ExcelProperty(value = "创建时间", index = 8)
private LocalDateTime createTime;
}
Mapper接口
package com.example.demo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
Service层
package com.example.demo.service;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.demo.entity.User;
import com.example.demo.mapper.UserMapper;
import com.example.demo.model.UserExcelDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
/**
* 导出用户数据
*/
public void exportUsers(HttpServletResponse response, String name) {
try {
// 设置响应头
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = URLEncoder.encode("用户数据_" + System.currentTimeMillis(), "UTF-8");
response.setHeader("Content-disposition",
"attachment;filename=" + fileName + ".xlsx");
// 查询数据
List<User> users = getUserList(name);
// 转换为DTO
List<UserExcelDTO> dataList = new ArrayList<>();
for (User user : users) {
UserExcelDTO dto = new UserExcelDTO();
BeanUtils.copyProperties(user, dto);
dataList.add(dto);
}
// 写入Excel
EasyExcel.write(response.getOutputStream(), UserExcelDTO.class)
.sheet("用户数据")
.doWrite(dataList);
} catch (IOException e) {
throw new RuntimeException("导出Excel失败", e);
}
}
/**
* 导入用户数据
*/
@Transactional(rollbackFor = Exception.class)
public List<UserExcelDTO> importUsers(MultipartFile file) {
List<UserExcelDTO> errorList = new ArrayList<>();
try {
EasyExcel.read(file.getInputStream(), UserExcelDTO.class,
new AnalysisEventListener<UserExcelDTO>() {
private List<UserExcelDTO> batchList = new ArrayList<>();
private static final int BATCH_SIZE = 100;
@Override
public void invoke(UserExcelDTO data, AnalysisContext context) {
// 数据验证
if (validateData(data)) {
batchList.add(data);
if (batchList.size() >= BATCH_SIZE) {
saveBatch(batchList);
batchList.clear();
}
} else {
errorList.add(data);
}
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
if (!batchList.isEmpty()) {
saveBatch(batchList);
batchList.clear();
}
}
}).sheet().doRead();
} catch (IOException e) {
throw new RuntimeException("导入Excel失败", e);
}
return errorList;
}
/**
* 批量保存用户
*/
private void saveBatch(List<UserExcelDTO> dtoList) {
List<User> userList = new ArrayList<>();
LocalDateTime now = LocalDateTime.now();
for (UserExcelDTO dto : dtoList) {
User user = new User();
BeanUtils.copyProperties(dto, user);
// 检查用户是否存在
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getUsername, dto.getUsername());
User existUser = userMapper.selectOne(wrapper);
if (existUser != null) {
user.setId(existUser.getId());
user.setUpdateTime(now);
userMapper.updateById(user);
} else {
user.setCreateTime(now);
user.setUpdateTime(now);
userMapper.insert(user);
}
}
}
/**
* 数据验证
*/
private boolean validateData(UserExcelDTO data) {
// 姓名和用户名不能为空
if (data.getName() == null || data.getName().isEmpty()) {
return false;
}
if (data.getUsername() == null || data.getUsername().isEmpty()) {
return false;
}
// 邮箱格式验证
if (data.getEmail() != null && !data.getEmail().isEmpty()) {
if (!data.getEmail().matches("^[A-Za-z0-9+_.-]+@(.+)$")) {
return false;
}
}
// 手机号格式验证
if (data.getPhone() != null && !data.getPhone().isEmpty()) {
if (!data.getPhone().matches("^1[3-9]\\d{9}$")) {
return false;
}
}
return true;
}
/**
* 查询用户列表
*/
private List<User> getUserList(String name) {
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
if (name != null && !name.isEmpty()) {
wrapper.like(User::getName, name);
}
wrapper.orderByDesc(User::getCreateTime);
return userMapper.selectList(wrapper);
}
}
Controller层
package com.example.demo.controller;
import com.example.demo.model.UserExcelDTO;
import com.example.demo.service.UserService;
import com.example.demo.util.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 导出用户数据
*/
@GetMapping("/export")
public void exportUsers(HttpServletResponse response,
@RequestParam(required = false) String name) {
userService.exportUsers(response, name);
}
/**
* 导入用户数据
*/
@PostMapping("/import")
public ResponseResult<List<UserExcelDTO>> importUsers(
@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return ResponseResult.error("上传文件不能为空");
}
// 检查文件格式
String filename = file.getOriginalFilename();
if (filename != null && !filename.endsWith(".xlsx") && !filename.endsWith(".xls")) {
return ResponseResult.error("文件格式不正确,请上传Excel文件");
}
try {
List<UserExcelDTO> errorList = userService.importUsers(file);
return ResponseResult.success(errorList);
} catch (Exception e) {
return ResponseResult.error("导入失败:" + e.getMessage());
}
}
/**
* 下载导入模板
*/
@GetMapping("/template")
public void downloadTemplate(HttpServletResponse response) {
userService.downloadTemplate(response);
}
}
通用响应类
package com.example.demo.util;
import lombok.Data;
@Data
public class ResponseResult<T> {
private Integer code;
private String message;
private T data;
public static <T> ResponseResult<T> success(T data) {
ResponseResult<T> result = new ResponseResult<>();
result.setCode(200);
result.setMessage("操作成功");
result.setData(data);
return result;
}
public static <T> ResponseResult<T> success(String message, T data) {
ResponseResult<T> result = new ResponseResult<>();
result.setCode(200);
result.setMessage(message);
result.setData(data);
return result;
}
public static <T> ResponseResult<T> error(String message) {
ResponseResult<T> result = new ResponseResult<>();
result.setCode(500);
result.setMessage(message);
return result;
}
public static <T> ResponseResult<T> error(Integer code, String message) {
ResponseResult<T> result = new ResponseResult<>();
result.setCode(code);
result.setMessage(message);
return result;
}
}
运行配置
# application.yml
server:
port: 8080
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/import_export_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: root
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto
前端测试页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">导入导出测试</title>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.6.2/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container mt-5">
<h2>用户数据导入导出</h2>
<div class="mt-4">
<!-- 导出功能 -->
<div class="card mb-4">
<div class="card-header">
<h5>导出用户数据</h5>
</div>
<div class="card-body">
<div class="form-group">
<label>按姓名筛选(可选)</label>
<input type="text" id="exportName" class="form-control"
style="max-width: 300px;" placeholder="请输入用户姓名">
</div>
<button class="btn btn-primary" onclick="exportUsers()">导出Excel</button>
</div>
</div>
<!-- 导入功能 -->
<div class="card">
<div class="card-header">
<h5>导入用户数据</h5>
</div>
<div class="card-body">
<div class="form-group">
<input type="file" id="importFile" class="form-control-file"
accept=".xlsx,.xls" style="max-width: 300px;">
</div>
<button class="btn btn-success" onclick="importUsers()">导入Excel</button>
<button class="btn btn-info" onclick="downloadTemplate()" style="margin-left: 10px;">
下载模板
</button>
</div>
</div>
<!-- 错误数据显示 -->
<div id="errorInfo" class="mt-4"></div>
</div>
</div>
<script>
// 导出用户数据
function exportUsers() {
const name = document.getElementById('exportName').value;
const params = new URLSearchParams();
if (name) {
params.append('name', name);
}
window.location.href = `/api/user/export?${params.toString()}`;
}
// 导入用户数据
function importUsers() {
const fileInput = document.getElementById('importFile');
const file = fileInput.files[0];
if (!file) {
alert('请选择要导入的Excel文件');
return;
}
const formData = new FormData();
formData.append('file', file);
fetch('/api/user/import', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.code === 200) {
alert('导入成功');
if (data.data && data.data.length > 0) {
displayErrors(data.data);
}
} else {
alert(data.message);
}
})
.catch(error => {
console.error('导入失败:', error);
alert('导入失败');
});
}
// 下载模板
function downloadTemplate() {
window.location.href = '/api/user/template';
}
// 显示错误数据
function displayErrors(errors) {
let html = '<h5>导入失败的数据:</h5>';
html += '<table class="table table-bordered">';
html += '<thead><tr><th>姓名</th><th>用户名</th><th>邮箱</th><th>错误信息</th></tr></thead>';
html += '<tbody>';
errors.forEach(error => {
const errorMsg = validateError(error);
html += `<tr>
<td>${error.name || '-'}</td>
<td>${error.username || '-'}</td>
<td>${error.email || '-'}</td>
<td class="text-danger">${errorMsg}</td>
</tr>`;
});
html += '</tbody></table>';
document.getElementById('errorInfo').innerHTML = html;
}
// 简单验证错误信息
function validateError(data) {
if (!data.name) return '姓名不能为空';
if (!data.username) return '用户名不能为空';
if (data.email && !isEmail(data.email)) return '邮箱格式不正确';
if (data.phone && !isPhone(data.phone)) return '手机号格式不正确';
return '其他错误';
}
function isEmail(email) {
return /^[^@]+@[^@]+\.[^@]+$/.test(email);
}
function isPhone(phone) {
return /^1[3-9]\d{9}$/.test(phone);
}
</script>
</body>
</html>
数据库建表SQL
CREATE DATABASE IF NOT EXISTS import_export_demo DEFAULT CHARACTER SET utf8mb4;
USE import_export_demo;
CREATE TABLE IF NOT EXISTS `user_info` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL COMMENT '姓名',
`username` VARCHAR(50) NOT NULL COMMENT '用户名',
`email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱',
`phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号',
`age` INT DEFAULT NULL COMMENT '年龄',
`address` VARCHAR(200) DEFAULT NULL COMMENT '地址',
`status` VARCHAR(20) DEFAULT 'active' COMMENT '状态',
`create_time` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户信息表';
测试用例
package com.example.demo;
import com.example.demo.service.UserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ImportExportDemoApplicationTests {
@Autowired
private UserService userService;
@Test
void contextLoads() {
// 测试数据导出逻辑
System.out.println("测试用例执行成功");
}
}
使用说明
-
启动项目:运行
ImportExportDemoApplication主类 -
API测试:
- 导出:
GET /api/user/export - 导入:
POST /api/user/import(上传Excel文件) - 模板下载:
GET /api/user/template
- 导出:
-
Excel文件格式:
- 第一行为列头(自动识别)
- 支持字段:用户ID、姓名、用户名、邮箱、手机号、年龄、地址、状态、创建时间
-
功能特点:
- 支持大数据量分批处理
- 导入时自动去重(按用户名)
- 数据验证和错误反馈
- 支持模板下载
这个案例提供了完整的导入导出功能,您可以根据实际需求进行调整和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播