谷粒学院
阿里云存储OSS
一、对象存储OSS
为了解决海量数据存储与弹性扩容,项目中我们采用云存储的解决方案 - 阿里云 OSS 。
1、开通“对象存储OSS”服务
( 0 )www.aliyun.com
( 1 )申请阿里云账号
( 2 )实名认证
( 3 )开通 “ 对象存储 OSS” 服务
( 4 )进入管理控制台
2、创建Bucket
选择:标准存储、公共读、不开通
3、上传默认头像
4、创建RAM子用户
一般在公司中,我们没有权限可以直接操作公司的阿里云账户,
所以我们需要获取创建阿里云OSS许可证(阿里云颁布id和秘钥
)
通过java代码上传
二、使用SDK
1、创建Maven项目
com.achang
aliyun-oss
2、pom
<!--aliyunOSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.1.0</version>
</dependency>
3、找到编码时需要用到的常量值
( 1 ) endpoint
( 2 ) bucketName
(3)accessKeyId
(4)accessKeySecret
4、测试创建Bucket的连接
创建存储空间:
// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录RAM控制台创建RAM账号。
String accessKeyId = "<yourAccessKeyId>";
String accessKeySecret = "<yourAccessKeySecret>";
String bucketName = "<yourBucketName>";
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 创建存储空间。
ossClient.createBucket(bucketName);
// 关闭OSSClient。
5、判断存储空间是否存在
@Test
public void testExist() {
// 创建OSSClient实例。
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
boolean exists = ossClient.doesBucketExist(bucketName);
System.out.println(exists);
// 关闭OSSClient。
ossClient.shutdown();
}
6、设置存储空间的访问权限
@Test
public void testAccessControl() {
// 创建OSSClient实例。
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 设置存储空间的访问权限为:公共读。
ossClient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
// 关闭OSSClient。
ossClient.shutdown();
}
讲师管理后端【上传讲师头像功能】
一、新建云存储微服务
1、在service模块下创建子模块service_oss
2、配置pom.xml
service_oss上级模块service已经引入service的公共依赖,所以service-oss模块只需引入阿里云oss相关依赖即,service父模块已经引入了service_base模块,所以Swagger相关默认已经引入
<!-- 阿里云oss依赖 -->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!--日期工具栏依赖-->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
3、配置application.properties
#服务端口
server.port=8002
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
#阿里云 OSS
#不同的服务器,地址不同
aliyun.oss.file.endpoint=oss-cn-hangzho3u.aliyuncs.com
aliyun.oss.file.keyid=LTAI4GBABS7Sq8M21Lf2RNwLuu
aliyun.oss.file.keysecret=ynfsD31FLdcRoQVFSI2dHP7AeoKaf4o
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=achang-edu
4、logback-spring.xml
5、创建启动类
6、启动项目
报错
spring boot 会默认加载 org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration 这个类,而 DataSourceAutoConfiguration 类使用了 @Configuration 注解向 spring 注入了 dataSource bean ,又因为项目( oss 模块)中并没有关于 dataSource 相关的配置信息,所以当 spring 创建 dataSource bean 时因缺少相关的信息就会报错。
解决办法:
在 @SpringBootApplication
注解上加上 exclude ,解除自动加载 DataSourceAutoConfiguration
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
二、实现文件上传
1、从配置文件读取常量
创建常量读取工具类:ConstantPropertiesUtil.java
使用@Value
读取application.properties里的配置内容
用spring的 InitializingBean 的 afterPropertiesSet 来初始化配置信息,这个方法将在所有的属性被初始化后调用。
//常量类,读取配置文件application.properties中的配置
@Component
public class ConstantPropertiesUtil implements InitializingBean {
@Value("${aliyun.oss.file.endpoint}")
private String endpoint;
@Value("${aliyun.oss.file.keyid}")
private String keyid;
@Value("${aliyun.oss.file.keysecret}")
private String keysecret;
@Value("${aliyun.oss.file.bucketname}")
private String bucketname;
public static String END_POINT;
public static String KEY_ID;
public static String KEY_SECRET;
public static String BUCKET_NAME;
@Override
public void afterPropertiesSet() throws Exception {
KEY_ID=this.keyid;
KEY_SECRET=this.keysecret;
END_POINT=this.endpoint;
BUCKET_NAME=this.bucketname;
}
}
2、文件上传
创建Service接口:OssService.java
public interface OssService {
//上传头像到OSS
String uploadFileAvatar(MultipartFile file);
}
实现:OssServiceImpl.java
参考SDK中的:Java->上传文件->简单上传->流式上传->上传文件流
@Service
public class OssServiceImpl implements OssService {
//上传头像到OSS
@Override
public String uploadFileAvatar(MultipartFile file) {
//工具类获取值
String endpoint = ConstantPropertiesUtil.END_POINT;
String accessKeyId = ConstantPropertiesUtil.KEY_ID;
String accessKeySecret = ConstantPropertiesUtil.KEY_SECRET;
String bucketName = ConstantPropertiesUtil.BUCKET_NAME;
InputStream inputStream = null;
try {
// 创建OSS实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
// 获取上传文件的输入流
inputStream = file.getInputStream();
//获取文件名称
String fileName = file.getOriginalFilename();
//调用oss实例中的方法实现上传
//参数1: Bucket名称
//参数2: 上传到oss文件路径和文件名称 /aa/bb/1.jpg
//参数3: 上传文件的输入流
ossClient.putObject(bucketName, fileName, inputStream);
// 关闭OSSClient。
ossClient.shutdown();
//把上传后文件路径返回
//需要把上传到阿里云oss路径手动拼接出来
//https://achang-edu.oss-cn-hangzhou.aliyuncs.com/default.gif
String url = "http://"+bucketName+"."+endpoint+"/"+fileName ;
return url;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
3、控制层
创建controller:OssController.java
@Api(description="阿里云文件管理")
@CrossOrigin //跨域
@RestController
@RequestMapping("/edu_oss/fileoss")
public class OssController {
@Autowired
private OssService ossService;
//上传头像
@ApiOperation(value = "文件上传")
@PostMapping("/upload")
public R uploadOssFile(@RequestParam("file") MultipartFile file){
//获取上传的文件
//返回上传到oss的路径
String url = ossService.uploadFileAvatar(file);
//返回r对象
return R.ok().data("url",url).message("文件上传成功");
}
}
4、重启oss服务
5、Swagger中测试文件上传
访问:http://localhost:8002/swagger-ui.html
测试通过
6、后端代码完善
- 测试
7、nginx回顾
8、配置nginx反向代理
nginx根目录/conf/nginx.conf配置,配置文件
修改nginx默认端口:
配置nginx转发规则:
下面的~
表示正则匹配,不加要求完全匹配
说明:当地址中包含eduservice
转发到8001端口,其他类似
server {
listen 9001;
server_name localhost;
location ~ /eduservice/ {
proxy_pass http://localhost:8001;
}
location ~ /edu_oss/ {
proxy_pass http://localhost:8002;
}
}
修改前端 端口号为9001:
- 测试
启动前端9528
启动nginx81,监听9001
9001会监听请求转发
启动后端8001、8002
讲师管理前端【上传头像功能】
一、创建上传组件
二、使用组件
guli-admin\src\views\edu\teacher\save.vue
<!-- 讲师头像:TODO -->
<!-- 讲师头像 -->
<el-form-item label="讲师头像">
<!-- 头衔缩略图 -->
<pan-thumb :image="teacher.avatar" />
<!-- 文件上传按钮 -->
<el-button
type="primary"
icon="el-icon-upload"
@click="imagecropperShow = true"
>更换头像
</el-button>
<!--
v-show:是否显示上传组件
:key:类似于id,如果一个页面多个图片上传控件,可以做区分
:url:后台上传的url地址
@close:关闭上传组件
@crop-upload-success:上传成功后的回调 -->
<image-cropper
v-show="imagecropperShow"
:width="300"
:height="300"
:key="imagecropperKey"
:url="BASE_API + '/admin/oss/file/upload'"
field="file"
@close="close"
@crop-upload-success="cropSuccess"
/>
</el-form-item>
引入组件模块
//引入头像组件
import ImageCropper from '@/components/ImageCropper'
import PanThumb from '@/components/PanThumb'
声明组件
export default {
//声明引入的组件
components:{ImageCropper,PanThumb},
...
}
给组件中用到的变量定义:
close(){ //关闭上传弹框的方法
this.imagecropperShow=false;
//上传组件初始化
this.imagecropperKey = this.imagecropperKey+1
},
cropSuccess(data){ //上传成功的方法
this.imagecropperShow=false;
//参数resp.data被封装到了方法参数data中了
this.teacher.avatar = data.url
this.imagecropperKey = this.imagecropperKey+1
}
三、js脚本上传和图片回显
四、测试文件上传
前后端联调
课程分类管理【环境搭建、Excel文件读取添加数据库】
0.课程分类存储结构
读写Excel表格导入:
一、数据库语句
CREATE TABLE `edu_subject` (
`id` char(19) NOT NULL COMMENT '课程类别ID',
`title` varchar(10) NOT NULL COMMENT '类别名称',
`parent_id` char(19) NOT NULL DEFAULT '0' COMMENT '父ID',
`sort` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '排序字段',
`gmt_create` datetime NOT NULL COMMENT '创建时间',
`gmt_modified` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_parent_id` (`parent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='课程科目';
#
# Data for table "edu_subject"
#
INSERT INTO `edu_subject` VALUES ('1178214681118568449','后端开发','0',1,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681139539969','Java','1178214681118568449',1,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681181483010','前端开发','0',3,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681210843137','JavaScript','1178214681181483010',4,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681231814658','云计算','0',5,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681252786178','Docker','1178214681231814658',5,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681294729217','Linux','1178214681231814658',6,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681324089345','系统/运维','0',7,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681353449473','Linux','1178214681324089345',7,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681382809602','Windows','1178214681324089345',8,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681399586817','数据库','0',9,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681428946945','MySQL','1178214681399586817',9,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681454112770','MongoDB','1178214681399586817',10,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681483472898','大数据','0',11,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681504444418','Hadoop','1178214681483472898',11,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681529610242','Spark','1178214681483472898',12,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681554776066','人工智能','0',13,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681584136193','Python','1178214681554776066',13,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681613496321','编程语言','0',14,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178214681626079234','Java','1178214681613496321',14,'2019-09-29 15:47:25','2019-09-29 15:47:25'),('1178585108407984130','Python','1178214681118568449',2,'2019-09-30 16:19:22','2019-09-30 16:19:22'),('1178585108454121473','HTML/CSS','1178214681181483010',3,'2019-09-30 16:19:22','2019-09-30 16:19:22');
二、EasyExcel读写Excel的基本使用
1、Excel导入导出的应用场景
-
数据导入:减轻录入工作量
-
数据导出:统计信息归档
-
数据传输:异构系统之间数据传输
2、EasyExcel简介
EasyExcel特点:
-
Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
-
EasyExcel是阿里巴巴开源的一个excel处理框架,
以使用简单、节省内存著称
。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。 -
EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。
三、EasyExcel写
1、创建项目,实现EasyExcel对Excel写操作
1)、引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
因为service已经引入,所以不用引入了,easyexcel:2.1.1
与poi:3.17
对应
2)、 创建实体类
要求:实体类属性和excel行列
设置表头和添加的数据字段
//设置表头和添加的数据字段
@Data
@ToString
public class DemoData {
//学生序号
//设置excel表头名称
@ExcelProperty("学生序号")
private Integer sno;
//学生名称
//设置excel表头名称
@ExcelProperty("学生姓名")
private String sname;
}
3)、实现写操作
创建方法循环设置要添加到Excel的数据(写法一)推荐
public class TestEasyExcel {
public static void main(String[] args) {
//实现excel写操作
//1、设置写入文件夹地址和excel文件名称
String filename="C:\\Users\\PePe\\Desktop\\DemoData.xlsx";
//调用easyExcel里面的方法实现写操作
//参数1:文件名称
//参数2:对应实体类
EasyExcel
.write(filename,DemoData.class)
.sheet("学生列表")
.doWrite(getLists());
}
//创建方法返回List集合
private static List<DemoData> getLists(){
ArrayList<DemoData> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
DemoData demoData = new DemoData();
demoData.setSno(i);
demoData.setSname("achang :"+ i);
list.add(demoData);
}
return list;
}
}
实现最终的添加操作(写法二)
public static void main(String[] args) {
//实现excel写操作
//1、设置写入文件夹地址和excel文件名称
String filename="C:\\Users\\PePe\\Desktop\\DemoData2.xlsx";
ExcelWriter excelWriter = EasyExcel.write(filename, DemoData.class)
.build();
WriteSheet build = EasyExcel.writerSheet("写入方法2").build();
// 这里 需要指定写用哪个class去写
excelWriter.write(getLists(),build);
// 千万别忘记finish 会帮忙关闭流
excelWriter.finish();
}
四、EasyExcel读
1、创建实体类
需要用index指定excel表格字段索引
//设置表头和添加的数据字段
@Data
@ToString
public class DemoData {
//学生序号
//设置excel表头名称
//index代表excel表格字段索引
@ExcelProperty(value = "学生序号",index = 0)
private Integer sno;
//学生名称
//设置excel表头名称
//index代表excel表格字段索引
@ExcelProperty(value = "学生姓名",index = 1)
private String sname;
}
2、创建读取操作的监听器
//创建读取excel监听器
public class ExcelListener extends AnalysisEventListener<DemoData> {
//创建list集合封装最终的数据
List<DemoData> list = new ArrayList<>();
//一行一行去读取excle内容
@Override
public void invoke(DemoData demoData, AnalysisContext analysisContext) {
System.out.println("***************"+demoData);
list.add(demoData);
}
//读取excel表头信息
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头信息========="+headMap);
}
//读取完成后执行
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
3、调用实现最终的读取
@Test
public void testReadExcel(){
String filename="C:\\Users\\PePe\\Desktop\\DemoData2.xlsx";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(filename,DemoData.class,new ExcelListener())
.sheet().doRead();
}
- 结果
五、课程分类添加功能_环境搭建
1、引入EasyExcel依赖
上面的service和service_edu已经引入了
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
2、使用代码生成器生成课程分类代码
因为还是在service_edu里面,所以其他都不用改变,只用在下面的5、
中修改为edu_subject
数据库表即可生成
public class CodeGenerator {
// @Test
public void run() {
// 1、创建代码生成器
AutoGenerator mpg = new AutoGenerator();
// 2、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir("D:\\JavaStudy\\gulixueyuan\\guli_parent\\service\\service_edu" + "/src/main/java"); //输出目录
gc.setAuthor("achang"); //作者名
gc.setOpen(false); //生成后是否打开资源管理器
gc.setFileOverride(false); //重新生成时文件是否覆盖
gc.setServiceName("%sService"); //去掉Service接口的首字母I
gc.setIdType(IdType.ID_WORKER_STR); //主键策略
gc.setDateType(DateType.ONLY_DATE);//定义生成的实体类中日期类型
gc.setSwagger2(true);//开启Swagger2模式
mpg.setGlobalConfig(gc);
// 3、数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/guli?serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("00000");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
// 4、包配置
PackageConfig pc = new PackageConfig();
//生成包:com.achang.eduservice
pc.setModuleName("eduservice"); //模块名
pc.setParent("com.achang");
//生成包:com.achang.oss.controller
pc.setController("controller");
pc.setEntity("entity");
pc.setService("service");
pc.setMapper("mapper");
mpg.setPackageInfo(pc);
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("edu_subject");//根据数据库哪张表生成,有多张表就加逗号继续填写
strategy.setNaming(NamingStrategy.underline_to_camel);//数据库表映射到实体的命名策略
strategy.setTablePrefix(pc.getModuleName() + "_"); //生成实体时去掉表前缀
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作
strategy.setRestControllerStyle(true); //restful api风格控制器
strategy.setControllerMappingHyphenStyle(true); //url中驼峰转连字符
mpg.setStrategy(strategy);
// 6、执行
mpg.execute();
}
}
六、课程分类读取Excel文件方法
1、EduSubjectController
com.achang.eduservice.controller.EduSubjectController
@RestController
@RequestMapping("/eduservice/edu-subject")
@CrossOrigin //解决跨域问题
@Api(description="课程分类管理")
public class EduSubjectController {
@Autowired
private EduSubjectService eduSubjectService;
//添加课程分类
//获取上传过来的文件,把文件内容读取出来
@PostMapping("/addSubject")
public R addSubject(MultipartFile file){
//获取上传的excel文件 MultipartFile
eduSubjectService.saveSubject(file,eduSubjectService);
//判断返回集合是否为空
return R.ok();
}
}
2、创建和Excel对应的实体类
@Data
@ToString
public class SubjectData {
//一级分类
@ExcelProperty(index = 0)
private String oneSubjectName;
//二级分类
@ExcelProperty(index = 1)
private String twoSubjectName;
}
3、SubjectExcelListener监听器
public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
//因为SubjectExcelListener態交给spring进行ioc管理,需要自己手动new,不能注入其他对象
//不能实现数据库操作
public EduSubjectService eduSubjectService;
//有参,传递subjectService用于操作数据库
public SubjectExcelListener(EduSubjectService eduSubjectService) {
this.eduSubjectService = eduSubjectService;
}
//无参
public SubjectExcelListener() {
}
//读取excel内容,一行一行读取
@Override
public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
//表示excel中没有数据,就不需要读取了
if (subjectData==null){
throw new AchangException(20001,"添加失败");
}
//一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类
//判断是否有一级分类是否重复
EduSubject existOneSubject = this.existOneSubject(eduSubjectService, subjectData.getOneSubjectName());
if (existOneSubject == null){ //没有相同的一级分类,进行添加
existOneSubject = new EduSubject();
existOneSubject.setParentId("0"); //设置一级分类id值,0代表为一级分类
existOneSubject.setTitle(subjectData.getOneSubjectName());//设置一级分类名
eduSubjectService.save(existOneSubject);//给数据库添加一级分类
}
//获取一级分类的id值
String parent_id = existOneSubject.getId();
//判断是否有耳机分类是否重复
EduSubject existTwoSubject = this.existTwoSubject(eduSubjectService, subjectData.getTwoSubjectName(), parent_id);
if (existTwoSubject==null){//没有相同的二级分类,进行添加
existTwoSubject = new EduSubject();
existTwoSubject.setParentId(parent_id); //设置二级分类id值
existTwoSubject.setTitle(subjectData.getTwoSubjectName());//设置二级分类名
eduSubjectService.save(existTwoSubject);//给数据库添加二级分类
}
}
//判断一级分类不能重复添加
private EduSubject existOneSubject(EduSubjectService eduSubjectService,String name){
QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
wrapper.eq("title",name)
.eq("parent_id","0");
EduSubject oneSubject = eduSubjectService.getOne(wrapper);
return oneSubject;
}
//判断二级分类不能重复添加
private EduSubject existTwoSubject(EduSubjectService eduSubjectService,String name,String parentId){
QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
wrapper.eq("title",name)
.eq("parent_id",parentId);
EduSubject twoSubject = eduSubjectService.getOne(wrapper);
return twoSubject;
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
4、SubjctService
1)接口
public interface EduSubjectService extends IService<EduSubject> {
//添加课程分类
void saveSubject(MultipartFile file,EduSubjectService eduSubjectService);
}
2)impl
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
//添加课程分类
@Override
public void saveSubject(MultipartFile file,EduSubjectService eduSubjectService) {
try {
//文件输入流
InputStream is = file.getInputStream();
//调用方法进行读取
EasyExcel.read(is, SubjectData.class,new SubjectExcelListener(eduSubjectService))
.sheet().doRead();
}catch (Exception e){
e.printStackTrace();
throw new AchangException(20002,"添加课程分类失败");
}
}
}
5、测试
先将数据库edu_subject
表中的数据清空测试
DELETE FROM edu_subject
启动8001端口
访问:localhost:8001/swagger-ui.html
传入01.xlsx,Excel文件
- 查看数据库是否有数据
成功添加