在线教育项目day6

项目第六天

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

(1)阿里云oss存储服务

2、添加课程分类功能(复杂)

(1)使用EasyExcel读取Excel内容添加数据

3、课程分类的列表

(1)树形结构显示

4、Nginx的使用

一、对象存储OSS

为了解决海量数据存储与弹性扩容,项目中我们采用云存储的解决方案- 阿里云OSS

1、打开阿里云网站

2、注册阿里云

3、登录阿里云

4、打开对象存储oss

5、开通存储对象oss

6、阿里云oss管理控制台的使用

(1)使用oss,首先创建bucket

在线教育项目day6_第1张图片
在线教育项目day6_第2张图片
在线教育项目day6_第3张图片

二、java代码操作oss

1、准备工作:创建操作阿里云oss许可证(阿里云颁发id和秘钥)

在这里插入图片描述
在这里插入图片描述
2、文档位置

在线教育项目day6_第4张图片
在线教育项目day6_第5张图片

// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 阿里云主账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建RAM账号。
String accessKeyId = "";
String accessKeySecret = "";
String bucketName = "";
// 上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
String objectName = "";

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

// 上传内容到指定的存储空间(bucketName)并保存为指定的文件名称(objectName)。
String content = "Hello OSS";
ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));

// 关闭OSSClient。
ossClient.shutdown();
			

三、上传讲师头像

1、新建maven service_oss

在线教育项目day6_第6张图片
在线教育项目day6_第7张图片

2、引入相关依赖

<dependencies>
    
    <dependency>
        <groupId>com.aliyun.ossgroupId>
        <artifactId>aliyun-sdk-ossartifactId>
    dependency>
    
    <dependency>
        <groupId>joda-timegroupId>
        <artifactId>joda-timeartifactId>
    dependency>
dependencies>

3、配置application.properties

#服务端口
server.port=8002
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev
        
#阿里云 OSS
#不同的服务器,地址不同
aliyun.oss.file.endpoint=your endpoint
aliyun.oss.file.keyid=your accessKeyId
aliyun.oss.file.keysecret=your accessKeySecret
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=guli-file

修改配置后如下所示

#服务端口
server.port=8002
#服务名
spring.application.name=service-oss
#环境设置:dev、test、prod
spring.profiles.active=dev

#阿里云 OSS
#不同的服务器,地址不同
aliyun.oss.file.endpoint=oss-cn-beijing.aliyuncs.com
aliyun.oss.file.keyid=LTAI4G7xYsEo22tATjUHWT4x
aliyun.oss.file.keysecret=G9dNSk9puPxhukjmm4Mfp4l5Jgx02T
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=edu-997

注意:

​ 秘钥不能加空格,前面或者后面都不能有

4、创建启动类

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

在线教育项目day6_第8张图片
​ spring boot 会默认加载org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration这个类,

​ 而DataSourceAutoConfiguration类使用了@Configuration注解向spring注入了dataSource bean,又因为项目(oss模块)中并没有关于dataSource相关的配置信息,所以当spring创建dataSource bean时因缺少相关的信息就会报错。

**解决方式:**在启动类添加属性,默认不去加载数据库配置

在线教育项目day6_第9张图片

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

在线教育项目day6_第10张图片
在线教育项目day6_第11张图片

//当项目已启动,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;
    }
}

6、创建controller、service

在线教育项目day6_第12张图片

编写controller

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

编写service,在service实现上传文件到oss过程

在阿里云的学习路径中copy,上传文件流

// Endpoint以杭州为例,其它Region请按实际情况填写。
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
// 云账号AccessKey有所有API访问权限,建议遵循阿里云安全最佳实践,创建并使用RAM子账号进行API访问或日常运维,请登录 https://ram.console.aliyun.com 创建。
String accessKeyId = "";
String accessKeySecret = "";

// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

// 上传文件流。
InputStream inputStream = new FileInputStream("");
ossClient.putObject("", "", inputStream);

// 关闭OSSClient。
ossClient.shutdown();
@Service
public class OssServiceImpl implements OssService {
    @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方法实现上传
            //第一个参数:bucket名称
            //第二个参数:上传到oss的文件路径和文件名称
            //第三个参数:上传文件的输入流
            ossClient.putObject(bucketName, fileName, inputStream);

        // 关闭OSSClient。
            ossClient.shutdown(); 
            //把上传之火文件路径返回
            //需要把上传到阿里云oss路径手动拼接出来
            String url="https://"+bucketName+"."+endpoint+"/"+fileName;
            return url;
        }catch (Exception e){
            
        }
      
        return null;
    }
}

7、添加随机唯一值

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

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

在线教育项目day6_第13张图片

8、把文件进行分类管理

根据日期进行分类

实现年月日分类
在线教育项目day6_第14张图片
在线教育项目day6_第15张图片

四、Nginx

Nginx 反向代理服务器

1、请求转发

什么是请求转发

在线教育项目day6_第16张图片

2、负载均衡

把请求平均分担到不同的服务中去

(到后面会用到网关)

在线教育项目day6_第17张图片

3、动静分离

4、安装

在线教育项目使用windows的Nginx足够了

特点:多路复用,使用cmd启动nginx,,需要使用nginx.exe -s stop手动停止停止

5、配置nginx.config

第一步:修改nginx默认端口 把80改为81
在线教育项目day6_第18张图片

第二步:配置nginx转发规则

server {
        listen      9001;//监听端口需要修改前端端口
        server_name  localhost;//主机

          location ~/serviceedu/ {
           proxy_pass http://localhost:8001;
        }
		location ~/eduoss/ {
		   proxy_pass http://localhost:8002;
		}
    }

五、添加讲师实现上传头像前端整合

1、在添加讲师页面,创建上传组件,实现上传使用element-ui组件实现

在线教育项目day6_第19张图片

复制到前端项目的src component里面

在线教育项目day6_第20张图片

2、在添加讲师页面使用组件



    
    
    
    更换头像
    
    
    

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200512000754166.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2NzAxODM4,size_16,color_FFFFFF,t_70)

3、引入组件和声明组件
在线教育项目day6_第21张图片

4、修改上传接口地址

在线教育项目day6_第22张图片

5、

在线教育项目day6_第23张图片
在线教育项目day6_第24张图片

六、EasyExcel

课程名称:java基础开发课程 分类:后端开发

课程名称:vue高级开发课程 分类:前端开发

在线教育项目day6_第25张图片
在线教育项目day6_第26张图片
parent_id=0时是一级分类

(1)Excel导入导出的应用场景

​ 1、数据导入:减轻录入工作量

​ 2、数据导出:统计信息归档

​ 3、数据传输:异构系统之间数据传输

(2)EasyExcel

  • Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
  • EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
  • EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。
1)使用easyExcel进行写操作

第一步:引入easyexcel依赖

<dependencies>
    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>easyexcelartifactId>
        <version>2.1.1version>
    dependency>
dependencies>
需要poi依赖

在线教育项目day6_第27张图片

第二步:

创建实体类,和Excel数据对应

在线教育项目day6_第28张图片

第三步:

新建

在线教育项目day6_第29张图片

public class TestEasyExcel {
    public static void main(String[] args) {
        //实现excel写操作
        //1、设置写入文件夹地址和excel文件名称
        String filename="F:\\write.xlsx";

        //2、调用easyExcel里面的方法来实现写操作
        //write里面的两个参数分别代表
        EasyExcel.write(filename,DemoDate.class).sheet("学生列表").doWrite(getData());
    }
    //创建方法返回list集合
    private static List<DemoDate> getData(){
        List<DemoDate> list=new ArrayList<>();
        for(int i=0;i<10;i++){
            DemoDate data=new DemoDate();
            data.setSname("lucy"+i);
            data.setSno(i);
            list.add(data);
        }
        return list;
    }
}

在线教育项目day6_第30张图片

2)使用easyExcel进行读操作

第一步:创建和excel对应实体类,标记对应列关系

在线教育项目day6_第31张图片

第二步:创建监听进行excel

在线教育项目day6_第32张图片

第三步:方法调用

在线教育项目day6_第33张图片
在线教育项目day6_第34张图片

七、课程分类管理(使用easyExcel)

课程分类添加功能

第一步:引入easyExcel依赖

第二步:使用代码生成器把课程分类代码生成

在线教育项目day6_第35张图片
在线教育项目day6_第36张图片
生成之后先在controller中解决跨域问题

@CrossOrigin

在线教育项目day6_第37张图片

第三步:创建实体类和excel对应的关系

在线教育项目day6_第38张图片

第四步:

在线教育项目day6_第39张图片
在线教育项目day6_第40张图片
在线教育项目day6_第41张图片
在线教育项目day6_第42张图片

package com.example.serviceedu.listener;


import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.servicebase.config.execptionhandler.ExampleException;
import com.example.serviceedu.entity.EduSubject;
import com.example.serviceedu.entity.excel.SubjectData;
import com.example.serviceedu.service.EduSubjectService;

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 ExampleException(20001,"文件数据为空");
        }

        //一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类
        //判断一级分类是否重复
        EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());
        if(existOneSubject == null) { //没有相同一级分类,进行添加
            existOneSubject = new EduSubject();
            existOneSubject.setParentId((long) 0);
            existOneSubject.setTitle(subjectData.getOneSubjectName());//一级分类名称
            subjectService.save(existOneSubject);
        }

        //获取一级分类id值
        long pid = existOneSubject.getId();

        //添加二级分类
        //判断二级分类是否重复
        EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);
        if(existTwoSubject == null) {
            existTwoSubject = new EduSubject();
            existTwoSubject.setParentId(pid);
            existTwoSubject.setTitle(subjectData.getTwoSubjectName());//二级分类名称
            subjectService.save(existTwoSubject);
        }
    }

    //判断一级分类不能重复添加
    private EduSubject existOneSubject(EduSubjectService subjectService,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(EduSubjectService subjectService,String name,long 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) {

    }
}

第二步:配置nginx转发规则

server {
        listen      9001;//监听端口需要修改前端端口
        server_name  localhost;//主机

          location ~/serviceedu/ {
           proxy_pass http://localhost:8001;
        }
		location ~/eduoss/ {
		   proxy_pass http://localhost:8002;
		}
    }

五、添加讲师实现上传头像前端整合

1、在添加讲师页面,创建上传组件,实现上传使用element-ui组件实现

在线教育项目day6_第43张图片

复制到前端项目的src component里面

在线教育项目day6_第44张图片

2、在添加讲师页面使用组件



    
    
    
    更换头像
    
    
    

在线教育项目day6_第45张图片

3、引入组件和声明组件
在线教育项目day6_第46张图片

4、修改上传接口地址

在线教育项目day6_第47张图片

5、

在线教育项目day6_第48张图片
在线教育项目day6_第49张图片

六、EasyExcel

课程名称:java基础开发课程 分类:后端开发

课程名称:vue高级开发课程 分类:前端开发

在线教育项目day6_第50张图片
在线教育项目day6_第51张图片
parent_id=0时是一级分类

(1)Excel导入导出的应用场景

​ 1、数据导入:减轻录入工作量

​ 2、数据导出:统计信息归档

​ 3、数据传输:异构系统之间数据传输

(2)EasyExcel

  • Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM或者JVM频繁的full gc。
  • EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
  • EasyExcel采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。
1)使用easyExcel进行写操作

第一步:引入easyexcel依赖

<dependencies>
    
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>easyexcelartifactId>
        <version>2.1.1version>
    dependency>
dependencies>
需要poi依赖

在线教育项目day6_第52张图片

第二步:

创建实体类,和Excel数据对应

在线教育项目day6_第53张图片

第三步:

新建
在线教育项目day6_第54张图片

public class TestEasyExcel {
    public static void main(String[] args) {
        //实现excel写操作
        //1、设置写入文件夹地址和excel文件名称
        String filename="F:\\write.xlsx";

        //2、调用easyExcel里面的方法来实现写操作
        //write里面的两个参数分别代表
        EasyExcel.write(filename,DemoDate.class).sheet("学生列表").doWrite(getData());
    }
    //创建方法返回list集合
    private static List<DemoDate> getData(){
        List<DemoDate> list=new ArrayList<>();
        for(int i=0;i<10;i++){
            DemoDate data=new DemoDate();
            data.setSname("lucy"+i);
            data.setSno(i);
            list.add(data);
        }
        return list;
    }
}

在线教育项目day6_第55张图片

2)使用easyExcel进行读操作

第一步:创建和excel对应实体类,标记对应列关系
在线教育项目day6_第56张图片

第二步:创建监听进行excel

在线教育项目day6_第57张图片

第三步:方法调用
在线教育项目day6_第58张图片

在线教育项目day6_第59张图片

七、课程分类管理(使用easyExcel)

课程分类添加功能

第一步:引入easyExcel依赖

第二步:使用代码生成器把课程分类代码生成

在线教育项目day6_第60张图片

在线教育项目day6_第61张图片

生成之后先在controller中解决跨域问题

@CrossOrigin

在线教育项目day6_第62张图片
第三步:创建实体类和excel对应的关系

在线教育项目day6_第63张图片

第四步:
在线教育项目day6_第64张图片
在线教育项目day6_第65张图片
在线教育项目day6_第66张图片
在线教育项目day6_第67张图片
在线教育项目day6_第68张图片

package com.example.serviceedu.listener;


import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.servicebase.config.execptionhandler.ExampleException;
import com.example.serviceedu.entity.EduSubject;
import com.example.serviceedu.entity.excel.SubjectData;
import com.example.serviceedu.service.EduSubjectService;

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 ExampleException(20001,"文件数据为空");
        }

        //一行一行读取,每次读取有两个值,第一个值一级分类,第二个值二级分类
        //判断一级分类是否重复
        EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());
        if(existOneSubject == null) { //没有相同一级分类,进行添加
            existOneSubject = new EduSubject();
            existOneSubject.setParentId((long) 0);
            existOneSubject.setTitle(subjectData.getOneSubjectName());//一级分类名称
            subjectService.save(existOneSubject);
        }

        //获取一级分类id值
        long pid = existOneSubject.getId();

        //添加二级分类
        //判断二级分类是否重复
        EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);
        if(existTwoSubject == null) {
            existTwoSubject = new EduSubject();
            existTwoSubject.setParentId(pid);
            existTwoSubject.setTitle(subjectData.getTwoSubjectName());//二级分类名称
            subjectService.save(existTwoSubject);
        }
    }

    //判断一级分类不能重复添加
    private EduSubject existOneSubject(EduSubjectService subjectService,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(EduSubjectService subjectService,String name,long 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) {

    }
}

你可能感兴趣的:(在线教育项目)