尚硅谷谷粒学院项目第六天内容之对象存储oss服务、使用EasyExcel添加课程分类功能、课程列表分类、ningx的使用

对象存储oss

打开阿里云官网——对象存储——oss管理控制台

创建bucket:选择默认地域、低频访问、公共读

创建oss许可证

对象存储oss——概览——常用入口——Access key

点击继续使用Accesskey

创建AccessKey——复制——确定

在service下创建SpringBoot子模块service_oss

引入依赖

<!-- 阿里云oss依赖 -->
<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!--日期工具栏依赖-->
<dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId>
</dependency>

配置application.properties

注意:地域节点、key、密钥要换成你自己的

#服务端口
server.port=8002
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
#阿里云 OSS
aliyun.oss.file.endpoint=oss-cn-hangzhou.aliyuncs.com
aliyun.oss.file.keyid=LTAI5t6R5cWusp7MeWpKgT1W
aliyun.oss.file.keysecret=Dd6Ku0j5dQja9jh4d7cl8ULepWcNE7
#bucket
aliyun.oss.file.bucketname=bucket--a

创建启动类,启动模块

报错

在启动类上添加:

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)

创建一个常量类,用来读取配置文件中的属性值

创建utils.ConstantRead类

@Component
public class ConstantRead 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 ENDPOINT;public static String KEY_ID;public static String KEY_SECRET;public static String BUCKET_NAME;@Overridepublic void afterPropertiesSet() throws Exception {ENDPOINT=endpoint;KEY_ID=keyId;KEY_SECRET=keySecret;BUCKET_NAME=bucketName;}
}

创建OssController

@RestController
@RequestMapping("/ossservice")
public class OssController {@Autowiredprivate OssService ossService;//上传头像@PostMapping("uploadAvatar")public R uploadFile(MultipartFile file){String url = ossService.uploadAvatar(file);return R.ok().data("url",url);}}

创建OssService

@Service
public interface OssService {//上传头像String uploadAvatar(MultipartFile file);
}

创建OssServiceImpl

@Component
public class OssServiceImpl implements OssService {@Overridepublic String uploadAvatar(MultipartFile file) {String endpoint = ConstantRead.ENDPOINT;String accessKeyId = ConstantRead.KEY_ID;String accessKeySecret = ConstantRead.KEY_SECRET;String bucketName = ConstantRead.BUCKET_NAME;String filename = file.getOriginalFilename();OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);try {InputStream inputStream = file.getInputStream();// 创建PutObject请求。ossClient.putObject(bucketName, filename, inputStream);} catch (Exception e) {e.printStackTrace();} finally {if (ossClient != null) {ossClient.shutdown();}}return "http://"+bucketName+"."+endpoint+"/"+filename;}
}

swagger测试

如果多个用户上传的文件名字相同,后上传的文件会把先上传的文件覆盖掉

我们在文件名前加上uuid值,让每个文件名都不同

在OssServiceImpl里添加

String filename = file.getOriginalFilename();
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
filename=uuid+filename;

此时上传的文件都是在bucket的根目录下

把文件按照日期进行分类

在OssServiceImpl里添加

String date = new DateTime().toString("yyyy/MM/dd");
filename=date+"/"+uuid+filename;

测试

nginx:反向代理服务器

功能:请求转发、负载均衡、动静分离

下载windows版的nginx,解压

在cmd中通过nginx.exe命令启动

关闭cmd窗口,nginx不会关闭

关闭nginx:nginx.exe -s stop

配置nginx实现请求转发功能

编辑nginx安装目录/conf/nginx.conf

将默认端口从80改为81,不改会端口冲突

添加端口映射规则

server {listen       9001;server_name  localhost;location ~ /eduservice/ {proxy_pass http://localhost:8001;}location ~ /ossservice/ {proxy_pass http://localhost:8002;}
}

将前端模板中config/dev.env.js中的BASE_API端口号改为9001

重启ningx、重启前后端,测试

讲师上传头像功能

将组件 ImageCropper和PanThumb 复制到项目中的 src/components 目录下

在save.vue中添加上传头像的组件

 <!-- 讲师头像 --><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,如果一个页面多个图片上传控件,可以做区分@crop-upload-success:上传成功后的回调 field:这个组件的name@close:关闭组件时会调用close()方法--><image-cropperv-show="imagecropperShow"  :width="300":height="300":key="imagecropperKey":url="BASE_API+'/eduoss/fileoss'"field="file"@close="close"@crop-upload-success="cropSuccess"/></el-form-item>

引入组件

import ImageCropper from '@/components/ImageCropper'
import PanThumb from '@/components/PanThumb'

声明组件

components: { ImageCropper, PanThumb },

定义变量

 imagecropperShow:false,imagecropperKey:0,BASE_API:process.env.BASE_API,

修改上传url

写两个方法

 close(){this.imagecropperShow=false},cropSuccess(data){ //data是后端返回的数据,相当于response.data,这里做了封装this.imagecropperShow=falsethis.teacher.avatar=data.url},

上传了头像后,再次点击更换头像,出现上传成功字样,而不是“将图片拖拽至此处”

解决:

改变imagecropperKey的值相当于让上传组件初始化

课程分类管理模块

课程分类使用二级分类:通过parentId实现

创建edu_subject表

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='课程科目';

向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

EasyExcel是处理excel表格的工具,将excel里的数据一行一行读进内存,高效简单

新建一个SpringBoot模块用来测试easyexcel

创建excel表格,用于测试

写操作

首先,引入依赖,easyecxel(2.1.1)+poi(3.17),版本之间有对应关系

        <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.1</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>3.17</version></dependency>

创建与excel表对应的实体类

@Data
public class Entity {@ExcelProperty("学生编号")private Integer sno;@ExcelProperty("学生姓名")private String name;
}

使用easyexcel向excel表格中写入数据

public class WriteTest {public static void main(String[] args) {String filename="F:\\temp\\test.xlsx";EasyExcel.write(filename,Entity.class).sheet("学生列表").doWrite(getData());//会自动关流}public static List<Entity> getData(){ArrayList<Entity> list = new ArrayList<>();for (int i=0;i<10;i++){Entity entity = new Entity();entity.setSno(i);entity.setName("lucy"+i);list.add(entity);}return list;}
}

执行结果

读操作

创建与excel表对应的实体类

@Data
public class ReadEntity {@ExcelProperty(value = "学生编号",index = 0)private Integer sno;@ExcelProperty(value = "学生姓名",index = 1)private String sname;
}

创建监听器

public class EasyExcelListener extends AnalysisEventListener<ReadEntity> {//一行一行读取数据(不读表头),数据封装在 readEntity@Overridepublic void invoke(ReadEntity readEntity, AnalysisContext analysisContext) {System.out.println(readEntity);}//读取表头@Overridepublic void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {System.out.println(headMap);}//读取完成后的处理@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) {}
}

使用easyexcel读excel表格的数据

public class ReadTest {public static void main(String[] args) {String filename="F:\\temp\\test.xlsx";EasyExcel.read(filename,ReadEntity.class,new EasyExcelListener()).sheet().doRead();}
}

执行结果

课程分类管理功能实现

生成代码框架:在service_edu模块,打开之前写的代码编辑器:src\test\java\com\jiabei\demo\CodeGenerator.java

修改数据库表名

执行后生成代码框架。

添加依赖

        <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>2.1.1</version></dependency>

创建与xlsx对应的实体类 com\jiabei\eduservice\entity\xlsx\SubjectSort.java

@Data
public class SubjectSort {@ExcelProperty(index=0)private String oneSubjectName;@ExcelProperty(index=1)private String twoSubjectName;
}

在实体类EduSubject中添加属性自动填充注解

    @TableId(value = "id", type = IdType.ID_WORKER_STR)private String id;    @TableField(fill=FieldFill.INSERT)private Date gmtCreate;@TableField(fill=FieldFill.INSERT_UPDATE)private Date gmtModified;

controller

@RestController
@RequestMapping("/eduservice/subject")
@CrossOrigin
public class EduSubjectController {@Autowiredprivate EduSubjectService subjectService;//添加学科类别:将上传的xlsx文件添加到数据库中@PostMapping("addSubjectSort")public R addSubjectSort(MultipartFile file){subjectService.addSubjectSort(file);return R.ok();}
}

service

public interface EduSubjectService extends IService<EduSubject> {void addSubjectSort(MultipartFile file);
}

serviceImpl

@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {@Autowiredprivate SubjectSortListener listener;@Overridepublic void addSubjectSort(MultipartFile file) {try {InputStream in = file.getInputStream();EasyExcel.read(in, SubjectSort.class,listener).sheet().doRead();//读取学科分类数据,listener.invoke()监听器负责将它们读到数据库}catch (Exception e){e.printStackTrace();}}
}

listener

@Component
public class SubjectSortListener extends AnalysisEventListener<SubjectSort> {@Autowiredprivate EduSubjectService subjectService;@Overridepublic void invoke(SubjectSort subjectSort, AnalysisContext analysisContext) {if (subjectSort==null){throw new GuliException(20001,"excel表中没有数据,读取失败");}String pid = addOne(subjectSort.getOneSubjectName());addTwo(subjectSort.getTwoSubjectName(),pid);}//添加一级分类private String addOne(String name){QueryWrapper<EduSubject> queryWrapper = new QueryWrapper<>();queryWrapper.eq("title",name);queryWrapper.eq("parent_id","0");EduSubject subject = subjectService.getOne(queryWrapper);//该分类是否已存在if (subject==null){//不存在时添加EduSubject s = new EduSubject();s.setParentId("0");s.setTitle(name);subjectService.save(s);}return subjectService.getOne(queryWrapper).getId();}//添加二级分类private void addTwo(String name,String pid){QueryWrapper<EduSubject> queryWrapper = new QueryWrapper<>();queryWrapper.eq("title",name);queryWrapper.eq("parent_id",pid);EduSubject subject = subjectService.getOne(queryWrapper);if(subject==null){EduSubject s = new EduSubject();s.setTitle(name);s.setParentId(pid);subjectService.save(s);}}@Overridepublic void doAfterAllAnalysed(AnalysisContext analysisContext) { }
}

将edu_subject表中数据清空,然后swagger测试,成功把excel表中的数据读到了数据库

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx相关推荐

  1. 尚硅谷谷粒学院学习笔记11-- 微信支付,课程详情页面功能完善

    课程支付需求描述 课程支付说明 (1)课程分为免费课程和付费课程,如果是免费课程可以直接观看,如果是付费观看的课程,用户需下单支付后才可以观看 (2)如果是免费课程,在用户选择课程,进入到课程详情页面 ...

  2. 尚硅谷谷粒学院学习笔记(防坑点的总结部分勘误)

    谷粒学院学习笔记 部分勘误 数据库设计规约 模块说明 环境搭建 创建一个Spring Boot 的父工程,版本使用:2.2.1.RELEASE 父工程pom.xml里面添加 在pom.xml中添加依赖 ...

  3. 谷粒学院项目对应知识点

    前言: 学习的谷粒学院项目,地址:尚硅谷-全栈在线教育项目-谷粒学院[Spring Boot + Spring Cloud Alibaba + Vue.js]_哔哩哔哩_bilibili 根据所学内容 ...

  4. 阿里云短信服务不对个人开放?如何在阿里云市场免费购买短信服务?云市场购买到的短信服务如何使用?(以谷粒学院项目为例)

    问题描述: 在做谷粒学院项目时,需要使用阿里云的短信服务用于注册验证,但是阿里云的短信服务目前不对个人开放了,看到弹幕说可以在云市场购买,于是果断尝试了一把,这过程中又遇到头疼的依赖版本兼容问题,好在 ...

  5. *谷粒商城项目笔记*

    谷粒商城项目笔记 一 项目介绍(略) 二分布式的基础概念 1,微服务 拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行 2, 集群是个物理形态,分布式是个工作方式. 例如:京东是个 ...

  6. 谷粒学院项目讲师管理(二)

    谷粒学院项目讲师管理 一.讲师列表 1.添加讲师列表路由 2.创建路由对应的vue页面 3.第三步在api文件夹创建teacher.js定义访问的接口地址 二.分页查询 三.条件查询 四.讲师添加 五 ...

  7. 谷粒学院(九)EasyExcel | 课程分类模块

    文章目录 一.EasyExcel 简介 1.Excel导入导出的应用场景 2.EasyExcel特点 3.案例1:EasyExcel进行Excel写操作 4.案例2:EasyExcel进行Excel读 ...

  8. 尚硅谷谷粒学院学习笔记9--前台用户登录,注册,整合jwt,微信登录

    用户登录业务 单点登录(Single Sign On),简称SSO. 用户只需要登陆一次就可以访问所有相互信任的应用系统 单点登录三种常见方式 session广播机制实现 使用redis+cookie ...

  9. 2022年最新《谷粒学院开发教程》:4 - 课程管理

    资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...

最新文章

  1. 轻松学习Linux之自动执行任务
  2. centos系统中kaptcha没有按指定的字体显示验证码问题解决
  3. 协同过滤——基于模型的算法
  4. arm opcode hook
  5. 画出微型计算机结构图,中级工792、画出计算机环形网络模式图.doc
  6. 创业失败感悟第二十九天
  7. android 重绘如何能不闪一下屏幕_回流和重绘
  8. 3D数学之矩阵的各种求逆
  9. 【Stanford Online】Engineering: Algorithms1 NO.5 QuickSort Algorithm
  10. 斯坦福NLP名课带学详解 | CS224n 第7讲 - 梯度消失问题与RNN变种(NLP通关指南·完结)
  11. 破解/忘记Win7密码
  12. VisualAge使用技巧(二)
  13. 联想win10进bios的正确方式,并不是按键!!!!!
  14. 统一论:3G手机、云计算、SaaS、业务开发平台、SOA、BPEL
  15. canvas示例样式_使用js canvas和atari vcs trivia制作基本html游戏的快速示例
  16. 拒了阿里offer,HR表示诧异,网友:这是你职业生涯的巅峰了
  17. SSH、SFTP、FTP、Telnet、SCP、TFTP协议的原理
  18. 使用java容器(集合类)模拟商城
  19. 约书亚·布洛赫(Joshua Bloch):Bumper-Sticker API设计
  20. Home Assistant 基于EZSP Zigbee Dongle创建Zigbee智能家居系统

热门文章

  1. RK3228H开发之Android开发
  2. 2018年全国多校算法寒假训练营练习比赛(第五场)F-The Biggest Water Problem
  3. 01-赵志勇机器学习-Logistics_Regression-train
  4. html中iframe显示多个子页面
  5. 齐博 src=/do/js.php?id=775,齐博CMS存储型XSS可getshell(组合利用)
  6. 【Atlas500】入门到放弃(六)——【DVPP】浅析HFBC格式数据存在的意义
  7. dtft频移性质_傅里叶变换纪实
  8. Sleep()简析 和Sleep(0)的妙用
  9. 德纳:Mecha《机甲变形》NFT元宇宙链游开发技术详情
  10. HTML简易时钟教程,html5 svg简单的模拟时钟特效-HTML5动画