谷粒学院第六天

在这里插入图片描述


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

1、阿里云 OSS 存储服务

在这里插入图片描述


(1)创建 Bucket
在这里插入图片描述


2、阿里 OSS 开发准备

(1)创建并查看 AccessKey

Java开发文档



3、实现头像上传功能

3.1 新建云存储微服务

(1)新建一个 service-oss 模块

在这里插入图片描述


(2)引入依赖

<!-- 阿里云 OSS 依赖 -->
<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
</dependency>

<!-- 日期工具类依赖 -->
<!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.9</version>
</dependency>

(3)编写 application.properties

#服务端口
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=LTAI5t9Gx1VdoJRW152qW6
aliyun.oss.file.keysecret=gEZiEZlPocddxIsFE2T101pTOhrwgN
#bucket可以在控制台创建,也可以使用java代码创建
aliyun.oss.file.bucketname=yanghui-guli

# 设置上传文件大小
spring.servlet.multipart.max-file-size=10MB

(4)创建启动类

/**
 * exclude = DataSourceAutoConfiguration.class:排除数据库自动配置
 * @ClassName OssApplication
 * @Author YH
 * @Date 2021/8/25
 * @Version 1.0
 */
@Slf4j
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@ComponentScan(value = {"com.yanghui"})
public class OssApplication {
    public static void main(String[] args) {
        SpringApplication.run(OssApplication.class, args);
        log.info("http://localhost:8001");
    }
}

3.2 实现文件上传

(1)编写常量类

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

    public static String KEY_SECRET;

    public static String  BUCKET_NAME;


    /**
     * 初始化 Bean 完成之后执行
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        END_POINT = endpoint;
        KEY_ID = keyId;
        KEY_SECRET = keySecret;
        BUCKET_NAME = bucketName;
    }
}

(2)编写 Controller

@RestController
@RequestMapping("/edu/oss")
@CrossOrigin
public class OssController {

    @Autowired
    private OssService ossService;


    /**
     * 上传文件
     * @param file
     * @return 文件的链接
     */
    @PostMapping
    public Result uploadFile(MultipartFile file) {
        String url = ossService.uploadFile(file);

        Map<String, Object> map = new HashMap<>();
        map.put("url", url);

        return Result.ok().data(map);
    }
}

(3)编写 Service 接口

public interface OssService {

    /**
     * 上传文件
     * @param file
     * @return
     */
    String uploadFile(MultipartFile file);
}

(4)编写 Service 接口实现类

@Service
public class OssServiceImpl implements OssService {


    @Override
    public String uploadFile(MultipartFile file){
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String endpoint = ConstantPropertiesUtils.END_POINT;
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = ConstantPropertiesUtils.KEY_ID;
        String accessKeySecret = ConstantPropertiesUtils.KEY_SECRET;
        String bucketName = ConstantPropertiesUtils.BUCKET_NAME;

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

            // 获取文件输入流
            InputStream inputStream = file.getInputStream();
            // 文件路径
            // 唯一值,避免相同文件名不能上传
            String uuid = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 7);
            // 按照日期分类(获取当前日期),调用 joda 的工具类
            String dateTime = new DateTime().toString("yyyy/MM/dd");
            String filePath = dateTime + "/" + uuid  + file.getOriginalFilename();
            // 依次填写Bucket名称(例如examplebucket)和Object完整路径(例如exampledir/exampleobject.txt)。Object完整路径中不能包含Bucket名称。
            ossClient.putObject(bucketName, filePath, inputStream);
            // 关闭OSSClient。
            ossClient.shutdown();

            Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 10);
            // 返回文件链接,没有对应的方法,需要自己拼接(老师的方法),经过查资料,企业中一般不这样干
            // String url = "https://" + bucketName + "." + endpoint + "/" + filePath;

            /**
             * 企业中常用的方式
             */
            URL url = ossClient.generatePresignedUrl(bucketName, filePath, expiration);
            return url.toString();
        } catch (Exception e) {
            e.printStackTrace();;
        }

        return null;
    }
}

(5)开始测试(使用 Swagger)

在这里插入图片描述



4、nginx

4.1 主要功能:


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


4.2 安装

nginx下载

解压后,cmd 进入所在目录,运行 nginx.exe 就可以启动了

停止命令:nginx -s stop


4.3 实现请求转发功能

(1)修改 nginx.conf 文件(在 nginx 安装目录 conf 目录下)

http 下添加以下内容:

# 添加配置
server {
    listen       9001;
    server_name  localhost;

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

}

(2)修改前端地址

在这里插入图片描述


(3)重启 nginx

运行命令 nginx -s stop ,然后再启动

(4)进行测试



5、前端实现

在这里插入图片描述




二、课程分类功能

在这里插入图片描述


1、数据库 SQL

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

#
# Data for table "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');


2、Easy Excel

2.1 Excel导入导出的应用场景

  • 数据导入:减轻录入工作量
  • 数据导出:统计信息归档
  • 数据传输:异构系统之间数据传输

2.2 EasyExcel简介

EasyExcel 特点:

  • Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内存。如果你的系统并发量不大的话可能还行,但是一旦并发上来后一定会OOM 或者 JVM 频繁的full gc。

  • EasyExcel 是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

  • EasyExcel 采用一行一行的解析模式,并将一行的解析结果以观察者的模式通知处理(AnalysisEventListener)。


2.3 Easy Exceyl 实现写操作

(1)引入依赖

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

(2)编写实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DemoData {
    /**
     * 设置表头
     */
    @ExcelProperty("学生编号")
    private Integer sno;

    /**
     * 属性值必须为小写,否则无法写入
     */
    @ExcelProperty("学生姓名")
    private String  sname;
}

(3)编写测试类

public class EasyExcelTest {

    public static void main(String[] args) {
        // 1 设置文件位置
        String fileName = "D:\\JAVA\\项目\\谷粒学院资料\\write.xlsx";
        // 2 实现写操作,学生列表:工作表名称
        EasyExcel.write(fileName, DemoData.class).sheet("学生列表").doWrite(getDemoData());

    }

    private static List<DemoData> getDemoData() {
        List<DemoData> demoDataList = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            DemoData data = new DemoData();
            data.setSno(i);
            data.setSname("yang" + i);
            System.out.println(data);
            demoDataList.add(data);
        }

        return  demoDataList;
    }
}

(4)测试结果
在这里插入图片描述


2.4 Easy Excel 实现读操作

(1)创建实体类

// 设置表头和添加的数据字段
@Data
@ToString
public class ReadData {

    /**
     * 设置 excel表头名称
     * index 代表 excel表格字段索引
     */
    @ExcelProperty(value = "学生序号", index = 0)
    private Integer sno;

    /**
     * 设置 excel表头名称
     * index代表excel表格字段索引
     */
    @ExcelProperty(value = "学生姓名", index = 1)
    private String sname;

}

(2)创建监听器

其实对数据的操作就是在这里完成的。

public class ExcelListener extends AnalysisEventListener<ReadData> {

    /**
     * 一行一行读取内容
     * @param data
     * @param context
     */
    @Override
    public void invoke(ReadData data, AnalysisContext context) {
        System.out.println("一、" + data);
    }

    /**
     * 读取完成之后
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }

    /**
     * 读取表头内容
     * @param headMap
     * @param context
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        System.out.println("表头:" + headMap);
    }
}

(3)测试类

public class EasyExcelReadTest {

    public static void main(String[] args) {
        String fileName = "D:\\JAVA\\项目\\谷粒学院资料\\write.xlsx";

        EasyExcel.read(fileName, ReadData.class, new ExcelListener()).sheet().doRead();
    }
}

(4)运行结果

在这里插入图片描述



3、添加课程分类

3.1 引入 Easy Excel 依赖

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

3.2 利用代码生成器生成相关代码

3.2 编写实体类

@Data
public class Subject {

    @ExcelProperty(index = 0)
    private String oneSubjectName;

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

3.3 编写 Contorller

@RestController
@RequestMapping("/eduservice/edu-subject")
public class EduSubjectController {

    @Autowired
    private EduSubjectService eduSubjectService;

    /**
     * 添加课程分类
     * 获取上传过来的文件
     */
    @PostMapping("/addSubject")
    public Result addSubject(MultipartFile multipartFile) {

        eduSubjectService.saveSubject(multipartFile, eduSubjectService);
        return Result.ok();
    }
}

3.4 编写 Service 接口

public interface EduSubjectService extends IService<EduSubject> {

    /**
     * 添加课程分类
     * @param multipartFile
     * @param eduSubjectService
     */
    void saveSubject(MultipartFile multipartFile, EduSubjectService eduSubjectService);
}

3.5 编写 Servie 接口实现类 ServiceImpl

@Service
public class EduSubjectServiceImpl extends ServiceImpl<EduSubjectMapper, EduSubject> implements EduSubjectService {

    @Override
    public void saveSubject(MultipartFile multipartFile, EduSubjectService eduSubjectService) {
        try {
            InputStream inputStream = multipartFile.getInputStream();
            EasyExcel.read(inputStream, Subject.class, new SubjectExcelListener(eduSubjectService)).sheet().doRead();
        } catch (Exception e) {

        }
    }
}

3.6 编写 Excel 监听器

public class SubjectExcelListener extends AnalysisEventListener<Subject> {

    private EduSubjectService eduSubjectService;

    public SubjectExcelListener() {

    }

    public SubjectExcelListener(EduSubjectService eduSubjectService) {
        this.eduSubjectService = eduSubjectService;
    }


    @Override
    public void invoke(Subject subject, AnalysisContext context) {
        if (subject == null) {
            throw new GuliException(500, "文件内容为空");
        }

        /**
         * 一级分类添加
         */
        EduSubject oneSubject = this.existOneSubject(this.eduSubjectService, subject.getOneSubjectName());
        // 如果没有相同的,就添加
        if (oneSubject == null) {
            oneSubject = new EduSubject();
            oneSubject.setParentId("0");
            oneSubject.setTitle(subject.getOneSubjectName());

            eduSubjectService.save(oneSubject);
        }

        /**
         * 主要是利用了 MybatisPlus 的添加之后会回显对象
         * 得到其父级 id
         */
        String parentId = oneSubject.getId();

        /**
         * 二级分类添加
         */
        EduSubject twoSubject = this.existTwoSubject(this.eduSubjectService, subject.getOneSubjectName(), parentId);
        // 如果没有相同的,就添加
        if (twoSubject == null) {
            EduSubject eduSubject = new EduSubject();
            eduSubject.setParentId(parentId);
            eduSubject.setTitle(subject.getTwoSubjectName());

            eduSubjectService.save(eduSubject);
        }

    }

    /**
     * 判断一级分类不能重复添加
     */
    private EduSubject existOneSubject(EduSubjectService eduSubjectService, String name) {
        QueryWrapper<EduSubject> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("title", name);
        queryWrapper.eq("parent_id", "0");

        EduSubject eduSubject = eduSubjectService.getOne(queryWrapper);

        return eduSubject;
    }

    /**
     * 判断二级分类不能重复添加
     */
    private EduSubject existTwoSubject(EduSubjectService eduSubjectService, String name, String parentId) {
        QueryWrapper<EduSubject> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("title", name);
        queryWrapper.eq("parent_id", parentId);

        EduSubject eduSubject = eduSubjectService.getOne(queryWrapper);

        return eduSubject;
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {

    }
}

3.6 使用 Swagger 进行测试

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值