在线教育-谷粒学院学习笔记(四)

news2024/11/15 8:47:15

文章目录

    • 1 内容介绍
    • 2 阿里云存储OSS
    • 3 Java代码操作阿里云oss
    • 4 搭建阿里云oss项目环境
    • 5 上传头像后端实现
    • 6 Nginx使用
    • 7 上传头像前端实现
    • 8 课程分类管理介绍
    • 9 EasyExcel工具
    • 10 课程分类添加功能

1 内容介绍

  • 添加讲师实现头像上传功能

    • 阿里云oss存储服务
  • 添加课程分类功能

    • 使用EasyExcel读取excel内容,添加数据
  • 课程分类的列表功能

    • 树形结构显示
  • Nginx使用

2 阿里云存储OSS

  • 登录阿里云官网,开通对象存储oss(在自己的账户中充几毛钱就行)

  • 管理控制台
    在这里插入图片描述

3 Java代码操作阿里云oss

  • 准备:创建操作阿里云oss许可证(id和密钥)
    • 创建AccessKey
      • LTAI5tDgYwJnddqgv7eseKUp
        dI3LnkakIe70taSwDTw6wspXQHN0xq
  • 示例代码
public static void main(String[] args) throws Exception {
    String endpoint = "oss-cn-chengdu.aliyuncs.com";
    String accessKeyId = "LTAI5tDgYwJnddqgv7eseKUp";
    String accessKeySecret = "dI3LnkakIe70taSwDTw6wspXQHN0xq";
    String bucketName = "edu-mys";

    // 创建OSSClient实例。
    OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    // 创建存储空间。
    ossClient.createBucket(bucketName);

4 搭建阿里云oss项目环境

  • 在service下创建service_oss子模块,并引入相关依赖

    <dependencies>
        <!-- 阿里云oss依赖 -->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
        </dependency>
        <!-- 日期工具栏依赖 -->
        <dependency>
            <groupId>joda-time</groupId>
            <artifactId>joda-time</artifactId>
        </dependency>
    </dependencies>
    
  • 创建配置配置文件:application.properties

    # 服务端口号
    server.port=8002
    # 服务名
    spring.application.name=service-oss
    # 环境设置
    spring.profiles.active=dev
    # 阿里云oss
    aliyun.oss.file.endpoint=oss-cn-chengdu.aliyuncs.com
    aliyun.oss.file.keyid=LTAI5tDgYwJnddqgv7eseKUp
    aliyun.oss.file.keysecret=dI3LnkakIe70taSwDTw6wspXQHN0xq
    # bucket可以在控制台创建,也可以java代码创建
    aliyun.oss.file.bucketname=edu-mys
    
  • 创建启动类 com/mys/oss/OssApplication.java

    @SpringBootApplication
    @ComponentScan(basePackages = {"com.mys"})
    public class OssApplication {
        public static void main(String[] args) {
            SpringApplication.run(OssApplication.class, args);
        }
    }
    
  • 启动

    • 报错:Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class

    • 原因:启动时找数据库配置,但当前模块不需要操作数据库,只是上传到oss功能,没有配置数据库

    • 解决

      • 添加数据库配置

      • 在启动类添加属性,默认不加载数据库配置(推荐)

        @SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
        

5 上传头像后端实现

1 创建常量类,读取配置文件内容

// 当项目一启动,spring加载之后,执行spring接口的一个方法
@Component
public class ConstantPropertiesUtils 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 ACCESS_KEY_ID;
    public static String ACCESS_KEY_SECRET;
    public static String BUCKET_NAME;

    @Override
    public void afterPropertiesSet() throws Exception {
        END_POINT = endpoint;
        ACCESS_KEY_ID = keyId;
        ACCESS_KEY_SECRET = keySecret;
        BUCKET_NAME = bucketName;
    }
}

2 创建controller

@RestController
@RequestMapping("/eduoss/fileoss")
@CrossOrigin
public class OssController {
    @Autowired
    private OssService ossService;
    // 上传头像方法
    @PostMapping
    public R uploadOssFile(MultipartFile file) {
        // 返回上传文件到oss的路径
        String url = ossService.uploadFileAvatar(file);
        return R.ok().data("url", url);
    }
}

3 service实现上传文件到oss过程

@Override
public String uploadFileAvatar(MultipartFile file) {
    // 通过工具类获取值
    String endpoint = ConstantPropertiesUtils.END_POINT;
    String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
    String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
    String bucketName = ConstantPropertiesUtils.BUCKET_NAME;

    try {
        // 创建OSSClient实例
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 获取上传文件的输入流
        InputStream inputStream = file.getInputStream();
        // 获取文件名称
        String fileName = file.getOriginalFilename();
        // 调用oss方法实现上传
        // 参数:bucketName;上传到oss文件路径和文件名称;上传文件输入流
        ossClient.putObject(bucketName, fileName, inputStream);
        // 关闭OSSClient
        ossClient.shutdown();

        // 把上传之后文件路径返回,需手动拼接上传到阿里云的oss路径
        // https://edu-mys.oss-cn-chengdu.aliyuncs.com/yy.JPG
        String url = "https://" + bucketName + "." + endpoint + "/" + fileName;
        return url;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

4 问题

  • 多次上传相同名称文件,造成最后一次上传把之前的文件覆盖

    • 解决:在文件名称添加随机唯一值,让每个文件名称不同

      // 在文件名称里添加随机唯一的值
      String uuid = UUID.randomUUID().toString().replaceAll("-", "");
      fileName = uuid + fileName;
      
  • 把文件进行分类管理

    • 根据用户分类

    • 根据日期分类,实现年月日分类

      // 把文件按照日期进行分类 2019/11/12/01.jpg
      // 获取当前日期
      String datePath = new DateTime().toString("yyyy/MM/dd");
      // 拼接
      fileName = datePath + "/" + fileName;
      

6 Nginx使用

  • 反向代理服务器

  • 功能

    • 请求转发
      在这里插入图片描述

    • 负载均衡:把请求平均分担到不同的服务器

    • 动静分离

  • 特点:多路复用;关闭窗口后nginx不会停止

    • 停止命令:nginx -s stop

配置nginx实现请求转发功能

  • 下载地址:http://nginx.org/en/download.html

  • 在nginx配置文件中进行配置 nginx.conf

    • 修改ngix默认端口 80->81

      server {
              listen       81;
              server_name  localhost;
              .....
      
    • 配置nginx转发规则

      在http中配置:
      server {
              listen       9001;
              server_name  localhost;
      
              location ~ /eduservice/ {
                  proxy_pass http://localhost:8001;
              }
              location ~ /eduoss/ {
                  proxy_pass http://localhost:8002;
              }
          }
      
  • 修改前端请求地址,改为nginx地址

    • conf/dev.env.js

    • BASE_API: '"http://localhost:9001"',
      
  • nginx重启并测试:先停止再启动

7 上传头像前端实现

1 在添加讲师页面,创建上传组件,实现上传

使用element-ui

找源码里的两个组件,复制到前端项目src/components里面 ImageCropper、PanThumb

2 添加讲师页面中写上传组件

      <!-- 讲师头像 -->
      <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+'/eduoss/fileoss'"
          field="file"
          @close="close"
          @crop-upload-success="cropSuccess"/>
      </el-form-item>

3 使用组件

data()定义变量和初始值

imagecropperShow: false, // 上传弹框组件是否显示
imagecropperKey: 0, // 上传组件key值
BASE_API: process.env.BASE_API, // 获取dev.env.js里面的地址
saveBtnDisabled: false // 保存按钮是否禁用

4 引入和声明组件

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

components: { ImageCropper, PanThumb },

5 修改上传接口的地址

:url="BASE_API+'/eduoss/fileoss'"

6 编写close方法和上传成功的方法

// 关闭上传弹框的方法
close() {
    this.imagecropperShow = false
    // 上传组件初始化
    this.imagecropperKey += 1
},
// 上传成功的方法
cropSuccess(data) {
    this.imagecropperShow = false
    this.imagecropperKey += 1
    // 上传之后接口返回图片地址
    this.teacher.avatar = data.url
},

8 课程分类管理介绍

  • 存储结构

在这里插入图片描述

  • 功能
    • 添加——表格
    • 列表

9 EasyExcel工具

  • 特点:一行行读取

  • 写操作

    1 引入依赖

    service_edu/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>
    

    还需要poi的依赖,注意版本对应

    2 创建实体类

    service_edu/test

    excel/DemoData.java

    @Data
    public class DemoData {
        // 设置表头名称
        @ExcelProperty("学生编号")
        private Integer sno;
        @ExcelProperty("学生姓名")
        private String name;
    }
    

    3 写操作

    public static void main(String[] args) {
        // 1 设置写入文件夹地址和excel名称
        String filename = "D:\\write.xlsx";
    
        // 2 调用easyexcel里面的方法实现写操作
        EasyExcel.write(filename, DemoData.class).sheet("学生列表").doWrite(getData());
    }
    
  • 读操作

    1 创建和excel对应实体类,标记对应列关系

    @Data
    public class DemoData {
        // 设置表头名称
        @ExcelProperty(value = "学生编号", index = 0)
        private Integer sno;
        @ExcelProperty(value = "学生姓名", index = 1)
        private String name;
    }
    

    2 创建监听进行excel文件读取

    public class ExcelListener extends AnalysisEventListener<DemoData> {
        // 一行一行读取excel内容
        @Override
        public void invoke(DemoData demoData, AnalysisContext analysisContext) {
            System.out.println("***" + demoData);
        }
    
        // 读取表头内容
        @Override
        public void invokeHead(Map<Integer, CellData> headMap, AnalysisContext context) {
            System.out.println("表头:" + headMap);
        }
    
        // 读取完成之后
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
        }
    }
    

    3 最终方法调用

    String filename = "D:\\write.xlsx";
    EasyExcel.read(filename, DemoData.class,  new ExcelListener()).sheet().doRead();
    

10 课程分类添加功能

1 引入EasyExcel依赖

2 使用代码生成器,生成课程分类的代码

CodeGenerator.java

3 创建实体类和excel对应关系

entity/excel/SubjectData.java

@Data
public class SubjectData {
    @ExcelProperty(index = 0)
    private String oneSubjectName;

    @ExcelProperty(index = 1)
    private String twoSubjectName;
}

**4 controller service **

@RestController
@RequestMapping("/eduservice/subject")
@CrossOrigin
public class EduSubjectController {
    @Autowired
    private EduSubjectService subjectService;
    // 添加课程分类,需要获取上传过来的文件,把文件内容读取出来
    @PostMapping("addSubject")
    public R addSubject(MultipartFile file) {
        // 上传过来的Excel文件
        subjectService.saveSubject(file, subjectService);
        return R.ok();
    }
}
@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {
    // 添加课程分类
    @Override
    public void saveSubject(MultipartFile file, EduSubjectService subjectService) {
        try {
            // 文件输入流
            InputStream in = file.getInputStream();
            // 调用方法进行读取
            EasyExcel.read(in, SubjectData.class, new SubjectExcelListener(subjectService)).sheet().doRead();
        } catch (Exception e) {
        }
    }
}

5 编写监听器SubjectExcelListener,处理excel文件

public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
    // 因为SubjectExcelListener不能交给spring管理,需要自己new,
    // 不能注入其他对象,不能实现操作数据库,需要自己写
    public EduSubjectService subjectService;
    public SubjectExcelListener() {}
    public SubjectExcelListener(EduSubjectService subjectService) {
        this.subjectService = subjectService;
    }
    // 读取excel内容,一行一行读取
    @Override
    public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
        if (subjectData == null) {
            throw new GuliException(20001, "文件数据为空");
        }
        // 一行行读取,每次读取两个值,第一个是一级分类,第二个是二级分类
        // 添加一级分类
        EduSubject existOneSubject = this.existOneSubject(subjectData.getOneSubjectName());
        if (existOneSubject == null) { // 没有相同的一级分类,进行添加
            existOneSubject = new EduSubject();
            existOneSubject.setParentId("0");
            existOneSubject.setTitle(subjectData.getOneSubjectName());
            subjectService.save(existOneSubject);
        }
        // 获取一级分类id
        String pid = existOneSubject.getId();
        // 添加二级分类
        EduSubject existTwoSubject = this.existTwoSubject(subjectData.getTwoSubjectName(), pid);
        if (existTwoSubject == null) { // 没有相同的一级分类,进行添加
            existTwoSubject = new EduSubject();
            existTwoSubject.setParentId("0");
            existTwoSubject.setTitle(subjectData.getTwoSubjectName());
            subjectService.save(existTwoSubject);
        }
    }
    // 判断一级分类不能重复添加
    private EduSubject existOneSubject(String name) {
        QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
        wrapper.eq("title", name);
        wrapper.eq("parent_id", 0);
        EduSubject oneSubject = subjectService.getOne(wrapper);
        return oneSubject;
    }
    // 判断二级分类不能重复添加
    private EduSubject existTwoSubject(String name, String pid) {
        QueryWrapper<EduSubject> wrapper = new QueryWrapper<>();
        wrapper.eq("title", name);
        wrapper.eq("parent_id", pid);
        EduSubject twoSubject = subjectService.getOne(wrapper);
        return twoSubject;
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/171397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

欧拉的“她力量”,如何为品牌注入新能量?

文|智能相对论作者| Kinki近日&#xff0c;百度营销联合CBNData推出的《2022新能源汽车趋势洞察》正式发布&#xff0c;报告显示&#xff0c;随着新能源汽车的普及&#xff0c;新中产女性已成为了“消费新势力”。女性更偏爱新能源汽车已不是新鲜观点&#xff0c;调研显示&…

物理主机telenet登录ensp虚拟网络设备并显示配置python脚本

一、物理主机telnet登录ensp虚拟网络设备 1、物理主机配置 1.1、物理主机环回口虚拟网卡配置 见本人博客:Ensp用windows回环口连接cloud配置_ensp环回口配置_林锋Space的博客-CSDN博客https://liulinfeng.blog.csdn.net/article/details/128098737 1.2、物理主机telnet开启 …

大数据的整体见解

如何建设高效的数据模型体系&#xff0c;使数据易用&#xff0c;避免重复建设和数据不一致性&#xff0c;保证数据的规范性&#xff1b;如何提供高效易用的数据开发工具&#xff1b;如何做好数据质量保障&#xff1b;如何有效管理和控制日益增长的存储和计算消耗&#xff1b;如…

文件下载 response响应ContentType与a标签download属性

参考资料 MediaType介绍了解HTML/HTML5中的download属性header中Content-Disposition的作用 目录一. ContentType二. a标签download属性2.1 下载同源静态资源文件2.2 后台可省略Content-Disposition一. ContentType 我们在进行文件下载的时候&#xff0c;后端往往需要通过如下…

CSRF(跨站请求伪造)

一、csrf是什么CSRF&#xff08;Cross Site Request Forgery&#xff0c;跨站请求伪造&#xff09;。是一种对网站的恶意利用&#xff0c;通过伪装来自受信任用户的请求来利用受信任的网站。原理是攻击者构造网站后台某个功能接口的请求地址&#xff0c;诱导用户去点击或者用特…

uni-app 中实现文件和图片的上传-H5

之前写过一篇上传的文章&#x1f4d5;&#xff0c;但是那篇文章仅仅只能实现上传图片的功能&#xff0c;而且代码写的比较乱&#xff0c;看起来很繁杂&#xff0c;最近有幸又遇到了上传图片和文件的需求&#xff0c;在完成这个功能后&#xff0c;整理一下&#xff0c;希望能给需…

第十四届蓝桥杯单片机组学习笔记(2):按键

第十四届蓝桥杯单片机组学习笔记&#xff08;2&#xff09;&#xff1a;按键前言区分高低电平驱动按键消抖软件消抖触发处理的方式矩阵键盘最简单常用的人机交互手段——按键 前言 实现按键检测需要解决的问题&#xff1a; 按键是低电平按下还是高电平按下&#xff1b;按键消…

(1分钟速览)KBM-SLAM 论文阅读笔记

编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;这篇博客记录了上面这篇论文的学习笔记。编辑切换为居中添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09;这个是本文的摘要&#xff0c;一眼开过去就是单目slam当今所遇到…

机器学习(一):人工智能概述

文章目录 人工智能概述 一、人工智能应用场景 二、人工智能小案例 三、人工智能发展必备三要素 四、人工智能、机器学习和深度学习 人工智能概述 一、人工智能应用场景 二、人工智能小案例 案例一 学习链接&#xff1a;https://quickdraw.withgoogle.com 案例二 学习链…

老杨说运维 | 2023,浅谈智能运维趋势(三)

文末附有视频回顾 前言&#xff1a; 在回顾&#xff08;一&#xff09;中&#xff0c;老杨提到的智能运维发展趋势中&#xff0c;面对国际化形势不确定的情况&#xff0c;信创部分的比例要求正在递增。作为国家经济发展的新动能&#xff0c;信创发展已步入深水区&#xff0c;智…

cv2.imread()、cv2.putText、cv2.imwrite()、cv2.waitKey()

cv2cv2.imread()cv2.putText&#xff08;&#xff09;cv2.imwrite&#xff08;&#xff09;cv2.waitKey()cv2.imread() 用于读取图像数据案例演示&#xff1a; import cv2# ouput img properties img_pathC:/Users/WHY/Pictures/Saved Pictures/OIP-C (1).jfif def funOutput…

安卓手机使用Linux Deploy安装CentOS

目录 前言 准备工作 实践 busybox安装 安装并配置Linux Deploy 局域网使用ssh连接服务器 公网使用ssh连接服务器 环境安装 写在最后 前言 最近沉迷于服务器搭建&#xff0c;书接上文&#xff0c;在安卓高版本中成功安装了服务器&#xff0c;但是安卓低版本的却一言难尽…

2023CUPT第七题 法拉第波 思路和解法

本文未完原题A droplet of less viscous liquid floating in a bath of a more viscous liquid develops surprising wave- like patterns when the entire system is set into vertical oscillation. Investigate this phenomenon and the parameters relevant to the product…

Webpack学习笔记

Webpack学习笔记1.引言2.Webpack相关的基础性问题3.Webpack的使用4.Webpack与代码规范和兼容性5.优化Html入口文件的处理6.实现webpack热更新7.生产模式与开发模式分析8.优化css配置&#xff0c;避免闪频现象9.代码压缩1.引言 最近想来自己对于前端的学习还是有很多的不足&…

毕业论文查重

每当毕业季论文编写都是一件大事&#xff0c;论文查重又是最让人头痛的事情&#xff0c;这里总结一些简单论文查重方法&#xff0c;希望对你有帮助。 首先通过一下系统查询重复比例&#xff0c;之后对照重复比例进行修改&#xff0c;如下图通过PaperPass论文检测进行查询生成的…

Linux安装JDK

创建develop目录 mkdir /usr/local/develop/ 我这边是直接将包拖进来了 创建jdk目录 mkdir /usr/local/develop/jdk/ 解压安装包 并且将安装文件放到 jdk目录里 tar -zxvf /usr/local/develop/jdk-8u191-linux-x64.tar.gz -C /usr/local/develop/jdk/ 或 tar -xvf /usr/l…

【信息系统项目管理师】论文写作心得整理篇

【信息系统项目管理师】论文写作心得整理篇 【信息系统项目管理师】论文写作心得整理篇【信息系统项目管理师】论文写作心得整理篇一.摘要二.论文评分标准1.切合题意2.应用深度和水平3.实践性4.表达能力5.综合能力和分析能力扣分项目加分项目不及格项目格式要求摘要的组成三.论…

Unity 工具 之 报错 Jenkins 执行/调用 Python 脚本,报错提示 ‘python‘ 不是内部或外部命令,也不是可运行的程序或批处理文件

Unity 工具 之 报错 Jenkins 执行/调用 Python 脚本&#xff0c;报错提示 python 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件 目录 Unity 工具 之 Jenkins 执行/调用 Python 脚本&#xff0c;报错提示 python 不是内部或外部命令&#xff0c;也不是可运行…

MyBatis -- 动态 SQL

MyBatis -- 动态 SQL动态 SQL 使用1. <if> 标签2. <trim> 标签3. <where> 标签4. <set> 标签5. <foreach> 标签动态 SQL 使用 动态 sql 是 Mybatis 的强大特性之⼀&#xff0c;能够完成不同条件下不同的 sql 拼接。 可以参考官方文档&#xff…

SNARK原理示例

1. 引言 前序博客有&#xff1a; SNARK DesignRollup项目的SNARK景观 SNARK方案由 Polynomial IOP ➕多项式承诺方案 组成。 当前的Polynomial IOP主要分为三大类&#xff1a; 1&#xff09;基于interactive proofs&#xff08;IPs&#xff09;的Polynomial IOP&#xff1…