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

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

对象存储oss

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

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

创建oss许可证

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

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第1张图片

 点击继续使用Accesskey

创建AccessKey——复制——确定

在service下创建SpringBoot子模块service_oss

引入依赖



    com.aliyun.oss
    aliyun-sdk-oss



    joda-time
    joda-time

配置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

创建启动类,启动模块

报错

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第2张图片

在启动类上添加:

@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;

    @Override
    public void afterPropertiesSet() throws Exception {
        ENDPOINT=endpoint;
        KEY_ID=keyId;
        KEY_SECRET=keySecret;
        BUCKET_NAME=bucketName;
    }
}

创建OssController

@RestController
@RequestMapping("/ossservice")
public class OssController {

    @Autowired
    private 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 {
    @Override
    public 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;
	  }
}

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第3张图片

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

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第4张图片

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

讲师上传头像功能

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

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

 
 
    
    
    
    更换头像
    
     
     
     

引入组件 

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

声明组件

 components: { ImageCropper, PanThumb }, 

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第5张图片

定义变量

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

修改上传url

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第6张图片

写两个方法

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

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

解决:

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

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第7张图片

 课程分类管理模块

 课程分类使用二级分类:通过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表格,用于测试

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第8张图片

写操作

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

        
            com.alibaba
            easyexcel
            2.1.1
        
        
            org.apache.poi
            poi
            3.17
        

创建与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 getData(){
        ArrayList 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;
    }
}

执行结果

谷粒学院项目笔记6——oss、EasyExcel、课程分类、nginx_第9张图片

 读操作

创建与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
    @Override
    public void invoke(ReadEntity readEntity, AnalysisContext analysisContext) {
        System.out.println(readEntity);
    }
    //读取表头
    @Override
    public void invokeHeadMap(Map headMap, AnalysisContext context) {
        System.out.println(headMap);
    }
    //读取完成后的处理
    @Override
    public 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

修改数据库表名

 执行后生成代码框架。

添加依赖

        
            com.alibaba
            easyexcel
            2.1.1
        

   

创建与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 {
    @Autowired
    private EduSubjectService subjectService;

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

service

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

serviceImpl

@Service
public class EduSubjectServiceImpl extends ServiceImpl implements EduSubjectService {

    @Autowired
    private SubjectSortListener listener;

    @Override
    public 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 {
    @Autowired
    private EduSubjectService subjectService;
    @Override
    public 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 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 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);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) { }
}

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

你可能感兴趣的:(谷粒学院,项目,阿里云,java,spring,boot)