使用VUE+SpringBoot+EasyExcel?整合導(dǎo)入導(dǎo)出數(shù)據(jù)的教程詳解
創(chuàng)建一個(gè)普通的maven項(xiàng)目即可
項(xiàng)目目錄結(jié)構(gòu)

1 前端
存放在resources/static 下
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<!-- 開(kāi)發(fā)環(huán)境版本,包含了有幫助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 引入樣式 -->
<link
rel="stylesheet"
rel="external nofollow"
/>
<!-- 引入組件庫(kù) -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<div class="app-container">
<div style="margin-bottom: 10px">
<el-button
@click="dialogVisible = true"
type="primary"
size="mini"
icon="el-icon-download"
>
導(dǎo)入Excel
</el-button>
<el-dialog
title="數(shù)據(jù)字典導(dǎo)入"
:visible.sync="dialogVisible"
width="30%"
>
<el-form>
<el-form-item label="請(qǐng)選擇Excel文件">
<el-upload
:auto-upload="true"
:multiple="false"
:limit="1"
:on-exceed="fileUploadExceed"
:on-success="fileUploadSuccess"
:on-error="fileUploadError"
:action="importUrl"
name="file"
accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
>
<!--accept 只接受某種格式的文件-->
<el-button size="small" type="primary">點(diǎn)擊上傳</el-button>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
</div>
</el-dialog>
<!-- 導(dǎo)出 -->
<el-button
@click="exportData"
type="primary"
size="mini"
icon="el-icon-upload2"
>
導(dǎo)出Excel
</el-button>
<!-- 數(shù)據(jù)展示 -->
<el-table :data="list" stripe style="width: 100%">
<el-table-column prop="name" label="姓名" width="180">
</el-table-column>
<el-table-column prop="birthday" label="生日" width="180">
</el-table-column>
<el-table-column prop="salary" label="薪資"> </el-table-column>
</el-table>
<div>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</div>
</div>
</div>
</body>
<script>
new Vue({
el: '#app',
data() {
return {
dialogVisible: false, //文件上傳對(duì)話框是否顯示
list: [], // 字典的數(shù)據(jù)
importUrl: 'http://localhost:8811/api/excel/import',
pageNum: 1, // 頁(yè)數(shù)
pageSize: 5, // 每頁(yè)條數(shù)
total: 1000,
}
},
created() {
this.showList()
},
methods: {
showList() {
//使用自定義配置
const request = axios.create({
baseURL: 'http://localhost:8811', //url前綴
timeout: 1000, //超時(shí)時(shí)間
// headers: { token: 'helen123456' }, //攜帶令牌
})
request
.get('/api/excel/list', {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
},
})
.then((res) => {
this.total = res.data.size
this.list = res.data.list
console.log(res)
})
},
// 上傳多于一個(gè)文件時(shí)
fileUploadExceed() {
this.$message.warning('只能選取一個(gè)文件')
},
// 導(dǎo)出
exportData() {
window.location.href = 'http://localhost:8811/api/excel/export'
},
//上傳成功回調(diào)
fileUploadSuccess(response) {
if (response.code === 0) {
this.$message.success('數(shù)據(jù)導(dǎo)入成功')
this.dialogVisible = false
} else {
this.$message.error(response.message)
}
},
//上傳失敗回調(diào)
fileUploadError(error) {
this.$message.error('數(shù)據(jù)導(dǎo)入失敗')
},
/**
* 用戶所選擇當(dāng)前頁(yè)面展示的數(shù)據(jù)條數(shù)
*/
handleSizeChange(val) {
console.log(`每頁(yè) ${val} 條`)
this.pageSize = val
this.showList()
},
handleCurrentChange(val) {
console.log(`當(dāng)前頁(yè): ${val}`)
this.pageNum = val
this.showList()
},
},
})
</script>
</html>
2 數(shù)據(jù)庫(kù)
CREATE TABLE `student` ( `name` varchar(255) DEFAULT NULL COMMENT '姓名', `birthday` datetime DEFAULT NULL COMMENT '生日', `salary` decimal(10,4) DEFAULT NULL COMMENT '薪資' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3 后端
3.1 contrller
StudentController
@Slf4j
@RestController
@CrossOrigin
@RequestMapping("/api/excel/")
public class StudentController {
@Resource
private StudentMapper studentMapper;
@GetMapping("list")
public HashMap<String, Object> list(@RequestParam int pageNum,@RequestParam int pageSize){
// 分頁(yè)查詢
Page<Student> page = new Page<>(pageNum, pageSize);
studentMapper.selectPage(page,null);
// 封裝數(shù)據(jù)
HashMap<String, Object> map = new HashMap<>();
ArrayList<ExcelStudentDTO> excelDictDTOList = new ArrayList<>();
// 轉(zhuǎn)換數(shù)據(jù)
page.getRecords().forEach(student -> {
ExcelStudentDTO studentDTO = new ExcelStudentDTO();
BeanUtils.copyProperties(student,studentDTO);
excelDictDTOList.add(studentDTO);
});
map.put("list",excelDictDTOList);
map.put("size",page.getTotal());
return map;
}
/**
* 導(dǎo)入
* @param file 文件對(duì)象
*/
@RequestMapping("import")
@Transactional(rollbackFor = {Exception.class})
public String importData( @RequestParam("file") MultipartFile file){
try {
// 讀取文件流
EasyExcel.read
(file.getInputStream(),// 前端上傳的文件
ExcelStudentDTO.class,// 跟excel對(duì)應(yīng)的實(shí)體類
new ExcelDictDTOListener(studentMapper))// 監(jiān)聽(tīng)器
.excelType(ExcelTypeEnum.XLSX)// excel的類型
.sheet("模板").doRead();
log.info("importData finished");
} catch (IOException e) {
log.info("失敗");
e.printStackTrace();
}
return "上傳成功";
}
/**
* 導(dǎo)入
*/
@GetMapping("export")
public String exportData(HttpServletResponse response){
try {
// 設(shè)置響應(yīng)體內(nèi)容
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 這里URLEncoder.encode可以防止中文亂碼 當(dāng)然和easyexcel沒(méi)有關(guān)系
String fileName = URLEncoder.encode("myStu", "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream()
,ExcelStudentDTO.class).sheet().doWrite(studentMapper.selectList(null));
} catch (Exception e) {
e.printStackTrace();
}
return "上傳成功";
}
}3.2 mapper
StudentMapper
@Mapper
public interface StudentMapper extends BaseMapper<Student> {
void insertBatch(List<ExcelStudentDTO> list);
}StudentMapper.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="look.word.mapper.StudentMapper">
<insert id="insertBatch" >
insert into student(name, birthday, salary)
values
<foreach collection="list" item="item" separator=",">
(
#{item.name} ,
#{item.birthday} ,
#{item.salary}
)
</foreach>
</insert>
</mapper>3.3 bean
ExcelStudentDTO
導(dǎo)入數(shù)據(jù)時(shí) 要保證excel中列名和ExcelStudentDTO一致奧
/**
* excel對(duì)應(yīng)的實(shí)體類
* @author jiejie
*/
@Data
public class ExcelStudentDTO {
// excel中的列名
@ExcelProperty("姓名")
private String name;
@ExcelProperty("生日")
private Date birthday;
@ExcelProperty("薪資")
private BigDecimal salary;
}Student
/**
* 數(shù)據(jù)庫(kù)對(duì)應(yīng)的實(shí)體類
* @author jiejie
*/
@Data
@TableName(value = "student")
public class Student {
/**
* 姓名
*/
@TableField(value = "name")
private String name;
/**
* 生日
*/
@TableField(value = "birthday")
private Date birthday;
/**
* 薪資
*/
@TableField(value = "salary")
private BigDecimal salary;
public static final String COL_NAME = "name";
public static final String COL_BIRTHDAY = "birthday";
public static final String COL_SALARY = "salary";
}3.4 listener
EasyExcel讀取文件需要用到
ExcelDictDTOListener
/**
* 監(jiān)聽(tīng)
* 再讀取數(shù)據(jù)的同時(shí) 對(duì)數(shù)據(jù)進(jìn)行插入操作
* @author : look-word
* @date : 2022-05-10 21:35
**/
@Slf4j
//@AllArgsConstructor //全參
@NoArgsConstructor //無(wú)參
public class ExcelDictDTOListener extends AnalysisEventListener<ExcelStudentDTO> {
/**
* 每隔5條存儲(chǔ)數(shù)據(jù)庫(kù),實(shí)際使用中可以3000條,然后清理list ,方便內(nèi)存回收
*/
private static final int BATCH_COUNT = 5;
List<ExcelStudentDTO> list = new ArrayList<ExcelStudentDTO>();
private StudentMapper studentMapper;
//傳入mapper對(duì)象
public ExcelDictDTOListener(StudentMapper studentMapper) {
this.studentMapper = studentMapper;
}
/**
*遍歷每一行的記錄
* @param data
* @param context
*/
@Override
public void invoke(ExcelStudentDTO data, AnalysisContext context) {
log.info("解析到一條記錄: {}", data);
list.add(data);
// 達(dá)到BATCH_COUNT了,需要去存儲(chǔ)一次數(shù)據(jù)庫(kù),防止數(shù)據(jù)幾萬(wàn)條數(shù)據(jù)在內(nèi)存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存儲(chǔ)完成清理 list
list.clear();
}
}
/**
* 所有數(shù)據(jù)解析完成了 都會(huì)來(lái)調(diào)用
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 這里也要保存數(shù)據(jù),確保最后遺留的數(shù)據(jù)也存儲(chǔ)到數(shù)據(jù)庫(kù)
saveData();
log.info("所有數(shù)據(jù)解析完成!");
}
/**
* 加上存儲(chǔ)數(shù)據(jù)庫(kù)
*/
private void saveData() {
log.info("{}條數(shù)據(jù),開(kāi)始存儲(chǔ)數(shù)據(jù)庫(kù)!", list.size());
studentMapper.insertBatch(list); //批量插入
log.info("存儲(chǔ)數(shù)據(jù)庫(kù)成功!");
}
}3.5 config
mybatisPlus分頁(yè)插件
MybatisPlusConfig
@Configuration
public class MybatisPlusConfig {
/**
* 新的分頁(yè)插件,一緩和二緩遵循mybatis的規(guī)則,
* 需要設(shè)置 MybatisConfiguration#useDeprecatedExecutor = false
* 避免緩存出現(xiàn)問(wèn)題(該屬性會(huì)在舊插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setDbType(DbType.MYSQL);
paginationInnerInterceptor.setOverflow(true);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}
@Bean
public ConfigurationCustomizer configurationCustomizer() {
return configuration -> configuration.setUseDeprecatedExecutor(false);
}
}3.6 配置文件
application.yaml
server:
port: 8811
spring:
datasource: # mysql數(shù)據(jù)庫(kù)連接
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/2022_source_springboot?serverTimezone=GMT%2B8&characterEncoding=utf-8
username: root
password: 317311
mybatis-plus:
configuration:# sql日志
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations:
- classpath:mapper/*.xml4 啟動(dòng)測(cè)試
啟動(dòng)springboot哦
頁(yè)面效果圖

導(dǎo)出效果

注意
導(dǎo)入數(shù)據(jù)時(shí) 要保證excel中列名和ExcelStudentDTO一致奧
到此這篇關(guān)于使用VUE+SpringBoot+EasyExcel 整合導(dǎo)入導(dǎo)出數(shù)據(jù)的文章就介紹到這了,更多相關(guān)vue springboot easyexcel導(dǎo)入導(dǎo)出數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot中EasyExcel實(shí)現(xiàn)Excel文件的導(dǎo)入導(dǎo)出
- SpringBoot 導(dǎo)出數(shù)據(jù)生成excel文件返回方式
- SpringBoot?整合?EasyExcel?實(shí)現(xiàn)自由導(dǎo)入導(dǎo)出功能
- SpringBoot整合EasyExcel實(shí)現(xiàn)批量導(dǎo)入導(dǎo)出
- springboot實(shí)現(xiàn)excel表格導(dǎo)出幾種常見(jiàn)方法
- SpringBoot整合EasyExcel實(shí)現(xiàn)文件導(dǎo)入導(dǎo)出
- SpringBoot+EasyPoi實(shí)現(xiàn)excel導(dǎo)出功能
- SpringBoot導(dǎo)出Excel的四種實(shí)現(xiàn)方式
- springboot實(shí)現(xiàn)對(duì)接poi 導(dǎo)出excel折線圖
相關(guān)文章
Vue中代碼編輯器與實(shí)時(shí)預(yù)覽功能
CodeMirror提供了強(qiáng)大的代碼編輯功能,而Vue.js使得組件的創(chuàng)建和數(shù)據(jù)綁定變得非常簡(jiǎn)單,當(dāng)用戶編輯代碼時(shí),實(shí)時(shí)預(yù)覽會(huì)根據(jù)代碼的變化進(jìn)行更新,從而為用戶提供了一個(gè)交互式的編程環(huán)境,這篇文章主要介紹了Vue中如何進(jìn)行代碼編輯器與實(shí)時(shí)預(yù)覽,需要的朋友可以參考下2023-10-10
Vue實(shí)現(xiàn)登錄功能全套超詳細(xì)講解(含封裝axios)
這篇文章主要給大家介紹了關(guān)于Vue實(shí)現(xiàn)登錄功能(含封裝axios)的相關(guān)資料,Vue是現(xiàn)在前端最流行的框架之一,作為前端開(kāi)發(fā)人員應(yīng)該要熟練的掌握它,需要的朋友可以參考下2023-10-10
vue使用router-view調(diào)用頁(yè)面方式
這篇文章主要介紹了vue使用router-view調(diào)用頁(yè)面方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
使用vue打包進(jìn)行云服務(wù)器上傳的問(wèn)題
這篇文章主要介紹了使用vue打包進(jìn)行云服務(wù)器上傳,本文給大家介紹的非常詳細(xì),對(duì)大家的工作或?qū)W習(xí)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03
解決vue scoped html樣式無(wú)效的問(wèn)題
這篇文章主要介紹了解決vue scoped html樣式無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
vue+drf+第三方滑動(dòng)驗(yàn)證碼接入的實(shí)現(xiàn)
這篇文章要給大家介紹的是vue和drf以及第三方滑動(dòng)驗(yàn)證碼接入的實(shí)現(xiàn),下文小編講詳細(xì)講解該內(nèi)容,感興趣的小伙伴可以和小編一起來(lái)學(xué)習(xí)奧2021-10-10
vue(element ui)使用websocket及心跳檢測(cè)方式
這篇文章主要介紹了vue(element ui)使用websocket及心跳檢測(cè)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07
詳解Jest結(jié)合Vue-test-utils使用的初步實(shí)踐
這篇文章主要介紹了詳解Jest結(jié)合Vue-test-utils使用的初步實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06

