尚医通_第6章_数据字典模块前后端+EasyExcel读写操作
文章目录
01-数据字典需求分析和搭建环境
一、数据字典介绍
1、什么是数据字典
数据字典就是管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、民族数据、行业数据、学历数据等,由于该系统大量使用这种数据,所以我们要做一个数据管理方便管理系统数据,一般系统基本都会做数据管理。
2、页面展示效果

3、数据字典表设计

4、数据分析

parent_id:
上级id,通过id与parent_id构建上下级关系,例如:我们要获取所有行业数据,那么只需要查询parent_id=20000的数据
name:名称,例如:填写用户信息,我们要select标签选择民族,“汉族”就是数据字典的名称
value:值,例如:填写用户信息,我们要select标签选择民族,“1”(汉族的标识)就是数据字典的值
dict_code:编码,编码是我们自定义的,全局唯一,例如:我们要获取行业数据,我们可以通过parent_id获取,但是parent_id是不确定的,所以我们可以根据编码来获取行业数据
说明:系统中会使用省市区三级联动数据,该数据我们来自“国家统计局”官方数据,地址:http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2019/index.html
5、根据页面效果分析数据接口
数据字典是树形展示,由于数据众多,我们使用“树形数据与懒加载”的方式展现数据列表,其他就是对数据的新增、修改与删除操作,因此需要提供的接口如下:
1,根据上级id获取下级数据(构造树形数据),参考文档:https://element.eleme.cn/#/zh-CN/component/table,页面搜索:树形数据与懒加载
2,导入接口
3,导出接口
二、搭建数据字典模块
1、创建service_cmn模块

2、创建application.properties配置文件
# 服务端口
server.port=8202
# 服务名
spring.application.name=service-cmn
# 环境设置:dev、test、prod
spring.profiles.active=dev
# mysql数据库连接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/yygh_cmn?characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=root123
#返回json的全局时间格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
spring.jackson.time-zone=GMT+8
3、使用代码生成器生成mapper接口,service,controller层,entity层生成之后删除!
代码生成器从yygh_hosp模块的拷贝[同时注意拷贝代码生成器的两个依赖哦]
4.创建启动类
@SpringBootApplication
@ComponentScan(basePackages = {"com.atguigu"})
public class ServiceCmnApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceCmnApplication.class, args);
}
}
5.创建一个Config配置类,扫描Mapper接口
@Configuration
@MapperScan("com.atguigu.yygh.cmn.mapper")
public class CmnConfig {
}
02-数据字典列表功能(前后端)
一、数据字典列表接口
根据element组件要求,返回列表数据必须包含hasChildren字典,如图:
https://element.eleme.cn/#/zh-CN/component/table


1、model模块添加数据字典实体**

@Data
@ApiModel(description = "数据字典")
@TableName("dict")
public class Dict {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@TableField("create_time")
private Date createTime;
@ApiModelProperty(value = "更新时间")
@TableField("update_time")
private Date updateTime;
@ApiModelProperty(value = "逻辑删除(1:已删除,0:未删除)")
@TableLogic
@TableField("is_deleted")
private Integer isDeleted;
@ApiModelProperty(value = "其他参数")
@TableField(exist = false)
private Map<String,Object> param = new HashMap<>();
@ApiModelProperty(value = "上级id")
@TableField("parent_id")
private Long parentId;
@ApiModelProperty(value = "名称")
@TableField("name")
private String name;
@ApiModelProperty(value = "值")
@TableField("value")
private String value;
@ApiModelProperty(value = "编码")
@TableField("dict_code")
private String dictCode;
@ApiModelProperty(value = "是否包含子节点")
@TableField(exist = false)
private boolean hasChildren;
}
说明:hasChildren为树形组件所需字典,标识为数据库表不存在该字段
2、添加数据字典mapper
public interface DictMapper extends BaseMapper<Dict> {
}
3、添加数据字典service
public interface DictService extends IService<Dict> {
//根据数据id查询子数据列表
List<Dict> findChlidData(Long id);
}
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
//根据数据id查询子数据列表
@Override
public List<Dict> findChlidData(Long id) {
QueryWrapper<Dict> wrapper = new QueryWrapper<>();
wrapper.eq("parent_id",id);
List<Dict> dictList = baseMapper.selectList(wrapper);
//向list集合每个dict对象中设置hasChildren
for (Dict dict:dictList) {
Long dictId = dict.getId();
boolean isChild = this.isChildren(dictId);
dict.setHasChildren(isChild);
}
return dictList;
}
//判断id下面是否有子节点
private boolean isChildren(Long id) {
QueryWrapper<Dict> wrapper = new QueryWrapper<>();
wrapper.eq("parent_id",id);
Integer count = baseMapper.selectCount(wrapper);
return count>0;
}
}
4、添加数据字典controller
@Api(description = "数据字典接口")
@RestController
@RequestMapping("/admin/cmn/dict")
@CrossOrigin
public class DictController {
@Autowired
private DictService dictService;
//根据数据id查询子数据列表
@ApiOperation(value = "根据数据id查询子数据列表")
@GetMapping("findChildData/{id}")
public R findChildData(@PathVariable Long id) {
List<Dict> list = dictService.findChlidData(id);
return R.ok().data("list",list);
}
}
二、数据字典列表前端
1、添加数据字典路由
修改router/index.js文件
{
path: '/cmn',
component: Layout,
redirect: '/cmn/list',
name: '数据管理',
alwaysShow: true,
meta: { title: '数据管理', icon: 'example' },
children: [
{
path: 'list',
name: '数据字典',
component: () => import('@/views/dict/list'),
meta: { title: '数据字典', icon: 'table' }
}
]
},
2、定义数据字典列表接口
创建文件 src/api/yygh/dict.js
import request from '@/utils/request'
export default {
dictList(id) {//数据字典列表
return request ({
url: `/admin/cmn/dict/findChildData/${id}`,
method: 'get'
})
}
}
3、在dict/list.vue调用
<script>
import dict from '@/api/yygh/dict'
export default {
data() {
return {
list:[] //数据字典列表数组
}
},
created() {
this.getDictList(1)
},
methods: {
//数据字典列表
getDictList(id) {
dict.dictList(id)
.then(response => {
this.list = response.data.list
})
},
load(tree, treeNode, resolve) {
dict.dictList(tree.id).then(response => {
resolve(response.data.list)
})
}
}
}
</script>
4、页面数据渲染
修改dict/list.vue页面
<template>
<div class="app-container">
<el-table
:data="list"
style="width: 100%"
row-key="id"
border
lazy
:load="load"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column
prop="name"
label="名称"
width="150">
</el-table-column>
<el-table-column
prop="dictCode"
label="编码"
width="150">
</el-table-column>
<el-table-column
prop="value"
label="值"
width="150">
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间">
</el-table-column>
</el-table>
</div>
</template>
03-技术点-EasyExcel介绍
一、EasyExcel介绍
1、数据导入:减轻录入工作量
2、数据导出:统计信息归档
3、数据传输:异构系统之间数据传输
二、EasyExcel特点
- Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
- EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
- EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
文档地址:https://alibaba-easyexcel.github.io/index.html
github地址:https://github.com/alibaba/easyexcel
1 导出示例
示例链接:https://alibaba-easyexcel.github.io/quickstart/write.html
2 导入示例
示例链接:https://alibaba-easyexcel.github.io/quickstart/read.html
3 EasyExcel集成
项目添加依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
04-技术点-EasyExcel写操作
一、创建项目,实现EasyExcel对Excel写操作
1、pom中引入xml相关依赖
<dependencies>
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
</dependencies>
2、创建实体类
设置表头和添加的数据字段
@Data
public class Stu {
//设置表头名称
@ExcelProperty("学生编号")
private int sno;
//设置表头名称
@ExcelProperty("学生姓名")
private String sname;
}
3 、实现写操作
(1)创建方法循环设置要添加到Excel的数据
//循环设置要添加的数据,最终封装到list集合中
private static List<Stu> data() {
List<Stu> list = new ArrayList<Stu>();
for (int i = 0; i < 10; i++) {
Stu data = new Stu();
data.setSno(i);
data.setSname("张三"+i);
list.add(data);
}
return list;
}
(2)实现最终的添加操作(写法一)
public static void main(String[] args) throws Exception {
// 写法1
String fileName = "F:\\11.xlsx";
// 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭
// 如果这里想使用03 则 传入excelType参数即可
EasyExcel.write(fileName, Stu.class).sheet("写入方法一").doWrite(data());
}
(3)实现最终的添加操作(写法二)
public static void main(String[] args) throws Exception {
// 写法2,方法二需要手动关闭流
String fileName = "F:\\112.xlsx";
// 这里 需要指定写用哪个class去写
ExcelWriter excelWriter = EasyExcel.write(fileName, Stu.class).build();
WriteSheet writeSheet = EasyExcel.writerSheet("写入方法二").build();
excelWriter.write(data(), writeSheet);
/// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
05-技术点-EasyExcel读操作
一、实现EasyExcel对Excel读操作
1、创建实体类
@Data
public class Stu {
//设置表头名称
//设置列对应的属性
@ExcelProperty(value = "学生编号",index = 0)
private int sno;
//设置表头名称
//设置列对应的属性
@ExcelProperty(value = "学生姓名",index = 1)
private String sname;
}
2、创建读取操作的监听器
public class ExcelListener extends AnalysisEventListener<Stu> {
//创建list集合封装最终的数据
List<Stu> list = new ArrayList<Stu>();
//一行一行去读取excle内容
@Override
public void invoke(Stu user, AnalysisContext analysisContext) {
System.out.println("***"+user);
list.add(user);
}
//读取excel表头信息
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头信息:"+headMap);
}
//读取完成后执行
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
3、调用实现最终的读取
public static void main(String[] args) throws Exception {
String fileName = "F:\\11.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, ReadData.class, new ExcelListener()).sheet().doRead();
}
06-数据字典导出功能(前后端)
一、数据字典导出后端接口
1、查看model实体类
在model模块查看实体:com.atguigu.yygh.vo.cmn.DictEeVo

@Data
public class DictEeVo {
@ExcelProperty(value = "id" ,index = 0)
private Long id;
@ExcelProperty(value = "上级id" ,index = 1)
private Long parentId;
@ExcelProperty(value = "名称" ,index = 2)
private String name;
@ExcelProperty(value = "值" ,index = 3)
private String value;
@ExcelProperty(value = "编码" ,index = 4)
private String dictCode;
}
2、在DictService添加方法和实现**
public interface DictService extends IService<Dict> {
/**
* 导出
* @param response
*/
void exportData(HttpServletResponse response);
}
@Override
public void exportData(HttpServletResponse response) {
try {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("数据字典", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
List<Dict> dictList = baseMapper.selectList(null);
List<DictEeVo> dictVoList = new ArrayList<>(dictList.size());
for(Dict dict : dictList) {
DictEeVo dictVo = new DictEeVo();
BeanUtils.copyProperties(dict,dictVo);
dictVoList.add(dictVo);
}
EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictVoList);
} catch (IOException e) {
e.printStackTrace();
}
}
3、添加Controller方法**
@ApiOperation(value="导出")
@GetMapping(value = "/exportData")
public void exportData(HttpServletResponse response) {
dictService.exportData(response);
}
二、数据字典导出前端
list.vue页面添加导出按钮
<div class="el-toolbar">
<div class="el-toolbar-body" style="justify-content: flex-start;">
<el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
</div>
</div>
编写调用方法
exportData() {
window.open("http://localhost:8202/admin/cmn/dict/exportData")
},
07-数据字典导入功能(前后端)
一、数据字典导入接口开发
1、创建读取监听器
@Component
public class DictListener extends AnalysisEventListener<DictEeVo> {
@Autowired
private DictMapper dictMapper;
//一行一行读取
@Override
public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
//调用方法添加数据库
Dict dict = new Dict();
BeanUtils.copyProperties(dictEeVo,dict);
dictMapper.insert(dict);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
2、添加controller方法
@ApiOperation(value = "导入")
@PostMapping("importData")
public R importData(MultipartFile file) {
dictService.importDictData(file);
return R.ok();
}
3、添加service方法
@Autowired
private DictListener dictListener;
@Override
public void importDictData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),DictEeVo.class,dictListener).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
二、数据字典导入前端
1、在list.vue页面添加导入按钮
<el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>
2、添加导入弹出层
<el-dialog title="导入":visible.sync="dialogImportVisible"width="480px">
<el-form label-position="right" label-width="170px">
<el-form-item label="文件">
<el-upload
:multiple="false"
:on-success="onUploadSuccess"
:action="'http://localhost:8202/admin/cmn/dict/importData'"
class="upload-demo">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogImportVisible = false">取消</el-button>
</div>
</el-dialog>
3、添加导入弹出层属性
data() {
return {
dialogImportVisible: false,
list:[] //数据字典列表数组
}
},
4、添加导入方法
importData() {
this.dialogImportVisible = true
},
onUploadSuccess(response, file) {
this.$message.info('上传成功')
this.dialogImportVisible = false
this.getDictList(1)
},
class="upload-demo">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogImportVisible = false">取消</el-button>
</div>
</el-dialog>
3、添加导入弹出层属性
data() {
return {
dialogImportVisible: false,
list:[] //数据字典列表数组
}
},
4、添加导入方法
importData() {
this.dialogImportVisible = true
},
onUploadSuccess(response, file) {
this.$message.info('上传成功')
this.dialogImportVisible = false
this.getDictList(1)
},

6031

被折叠的 条评论
为什么被折叠?



