谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx
尚硅谷谷粒学院项目第六天内容之对象存储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相关推荐
- 尚硅谷谷粒学院学习笔记11-- 微信支付,课程详情页面功能完善
课程支付需求描述 课程支付说明 (1)课程分为免费课程和付费课程,如果是免费课程可以直接观看,如果是付费观看的课程,用户需下单支付后才可以观看 (2)如果是免费课程,在用户选择课程,进入到课程详情页面 ...
- 尚硅谷谷粒学院学习笔记(防坑点的总结部分勘误)
谷粒学院学习笔记 部分勘误 数据库设计规约 模块说明 环境搭建 创建一个Spring Boot 的父工程,版本使用:2.2.1.RELEASE 父工程pom.xml里面添加 在pom.xml中添加依赖 ...
- 谷粒学院项目对应知识点
前言: 学习的谷粒学院项目,地址:尚硅谷-全栈在线教育项目-谷粒学院[Spring Boot + Spring Cloud Alibaba + Vue.js]_哔哩哔哩_bilibili 根据所学内容 ...
- 阿里云短信服务不对个人开放?如何在阿里云市场免费购买短信服务?云市场购买到的短信服务如何使用?(以谷粒学院项目为例)
问题描述: 在做谷粒学院项目时,需要使用阿里云的短信服务用于注册验证,但是阿里云的短信服务目前不对个人开放了,看到弹幕说可以在云市场购买,于是果断尝试了一把,这过程中又遇到头疼的依赖版本兼容问题,好在 ...
- *谷粒商城项目笔记*
谷粒商城项目笔记 一 项目介绍(略) 二分布式的基础概念 1,微服务 拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行 2, 集群是个物理形态,分布式是个工作方式. 例如:京东是个 ...
- 谷粒学院项目讲师管理(二)
谷粒学院项目讲师管理 一.讲师列表 1.添加讲师列表路由 2.创建路由对应的vue页面 3.第三步在api文件夹创建teacher.js定义访问的接口地址 二.分页查询 三.条件查询 四.讲师添加 五 ...
- 谷粒学院(九)EasyExcel | 课程分类模块
文章目录 一.EasyExcel 简介 1.Excel导入导出的应用场景 2.EasyExcel特点 3.案例1:EasyExcel进行Excel写操作 4.案例2:EasyExcel进行Excel读 ...
- 尚硅谷谷粒学院学习笔记9--前台用户登录,注册,整合jwt,微信登录
用户登录业务 单点登录(Single Sign On),简称SSO. 用户只需要登陆一次就可以访问所有相互信任的应用系统 单点登录三种常见方式 session广播机制实现 使用redis+cookie ...
- 2022年最新《谷粒学院开发教程》:4 - 课程管理
资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...
最新文章
- 轻松学习Linux之自动执行任务
- centos系统中kaptcha没有按指定的字体显示验证码问题解决
- 协同过滤——基于模型的算法
- arm opcode hook
- 画出微型计算机结构图,中级工792、画出计算机环形网络模式图.doc
- 创业失败感悟第二十九天
- android 重绘如何能不闪一下屏幕_回流和重绘
- 3D数学之矩阵的各种求逆
- 【Stanford Online】Engineering: Algorithms1 NO.5 QuickSort Algorithm
- 斯坦福NLP名课带学详解 | CS224n 第7讲 - 梯度消失问题与RNN变种(NLP通关指南·完结)
- 破解/忘记Win7密码
- VisualAge使用技巧(二)
- 联想win10进bios的正确方式,并不是按键!!!!!
- 统一论:3G手机、云计算、SaaS、业务开发平台、SOA、BPEL
- canvas示例样式_使用js canvas和atari vcs trivia制作基本html游戏的快速示例
- 拒了阿里offer,HR表示诧异,网友:这是你职业生涯的巅峰了
- SSH、SFTP、FTP、Telnet、SCP、TFTP协议的原理
- 使用java容器(集合类)模拟商城
- 约书亚·布洛赫(Joshua Bloch):Bumper-Sticker API设计
- Home Assistant 基于EZSP Zigbee Dongle创建Zigbee智能家居系统
热门文章
- RK3228H开发之Android开发
- 2018年全国多校算法寒假训练营练习比赛(第五场)F-The Biggest Water Problem
- 01-赵志勇机器学习-Logistics_Regression-train
- html中iframe显示多个子页面
- 齐博 src=/do/js.php?id=775,齐博CMS存储型XSS可getshell(组合利用)
- 【Atlas500】入门到放弃(六)——【DVPP】浅析HFBC格式数据存在的意义
- dtft频移性质_傅里叶变换纪实
- Sleep()简析 和Sleep(0)的妙用
- 德纳:Mecha《机甲变形》NFT元宇宙链游开发技术详情
- HTML简易时钟教程,html5 svg简单的模拟时钟特效-HTML5动画