• 2022年最新《谷粒学院开发教程》:6 - 整合SpringCloud




    一、服务注册中心搭建

    需要将nacos和mysql放在自定义的同一个网络中并通过服务名连接,否则每次重新启动容器都会重新分配虚拟ip

    1、创建自定义网络

    docker network create guli
    
    • 1

    2、运行mysql(用于保存nacos配置信息)

    mkdir -p /mydata/guli/mysql/conf
    vim /mydata/guli/mysql/conf/my.cnf 
    
    ############## my.cnf #####################
    [client]
    default-character-set=utf8
    [mysql]
    default-character-set=utf8
    [mysqld]
    init_connect='SET collation_connection = utf8_unicode_ci'
    init_connect='SET NAMES utf8'
    character-set-server=utf8
    collation-server=utf8_unicode_ci
    skip-character-set-client-handshake
    skip-name-resolve
    ###########################################
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    docker run -p 3306:3306 --name guli_mysql \
    --privileged=true \
    -v /mydata/guli/mysql/log:/var/log/mysql \
    -v /mydata/guli/mysql/data:/var/lib/mysql \
    -v /mydata/guli/mysql/conf:/etc/mysql \
    -e MYSQL_ROOT_PASSWORD=root \
    --network guli \
    --restart=always \
    -d mysql:5.7
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3、创建数据库 nacos(Character-set:utf8,Collation: utf8_bin)执行 数据库脚本

    4、运行nacos测试容器

    mkdir -p /mydata/guli/nacos/logs
    mkdir -p /mydata/guli/nacos/conf
    
    docker run -d --name test nacos/nacos-server
    
    docker cp test:/home/nacos/conf /mydata/guli/nacos
    
    docker rm -f test
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5、运行Nacos容器(MYSQL_SERVICE_HOST=guli_mysql 通过服务名连接)

    docker run --name guli_nacos \
    -e JVM_XMS=256m \
    -e JVM_XMX=256m \
    -e PREFER_HOST_MODE=ip \
    -e MODE=standalone \
    -e SPRING_DATASOURCE_PLATFORM=mysql \
    -e MYSQL_SERVICE_HOST=guli_mysql \
    -e MYSQL_SERVICE_PORT=3306 \
    -e MYSQL_SERVICE_USER=root \
    -e MYSQL_SERVICE_PASSWORD=root \
    -e MYSQL_SERVICE_DB_NAME=nacos \
    -v /mydata/guli/nacos/logs:/home/nacos/logs \
    -v /mydata/guli/nacos/conf:/home/nacos/conf \
    -p 8848:8848 \
    --network guli \
    --restart=always \
    -d nacos/nacos-server
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6、访问 - IP地址:8848/nacos 创建配置并查看是否持久化成功


    二、服务注册

    1、service模块 POM引入依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4

    2、每个子模块配置YML

    spring: 
      cloud:
        nacos:
          discovery:
            server-addr: ip:8848
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3、每个主启动类添加注解 @EnableDiscoveryClient

    4、效果

    在这里插入图片描述


    三、服务调用

    需求:删除课时的同时删除云端视频

    1、在service模块添加pom依赖

    <!--服务调用-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、调用端 service_edu 启动类添加注解 (如删除课时同时删除云端视频)

    @EnableFeignClients(basePackages = "com.laptoy.eduservice.client")
    
    • 1

    3、远程调用业务

    package com.laptoy.eduservice.client;
    
    @FeignClient("service-vod")//指定调用的服务名,前提要注册到nacos注册中心中
    public interface VodClient {
    
        // 根据视频id删除阿里云视频
        @DeleteMapping("/eduvod/video/removeAliyunVideoById/{id}")
        public R removeAliyunVideoById(@PathVariable("id") String id);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、优化控制层

    //删除小节同时删除云端视频
    @DeleteMapping("/deleteVideo/{id}")
    public R deleteVideo(@PathVariable String id) {
        eduVideoService.removeVideoByVideoId(id);
        return R.ok();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5、优化删除小节业务

    @Service
    public class EduVideoServiceImpl extends ServiceImpl<EduVideoMapper, EduVideo> implements EduVideoService {
    
        @Autowired
        VodClient vodClient;
    
        // 根据小节id删除小节视频
        @Override
        public void removeVideoByVideoId(String id) {
            EduVideo eduVideo = this.getById(id);
            
            String videoSourceId = eduVideo.getVideoSourceId();
            if (!StringUtils.isEmpty(videoSourceId)) {
                // 删除小节的视频
                vodClient.removeAliyunVideoById(videoSourceId);
            }
            // 删除小节
            baseMapper.deleteById(id);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    6、测试

    添加小节并上传视频 - 删除小节查看云端

    在这里插入图片描述


    四、完整删除课程业务

    需求:删除课程的同时删除云端视频,要求添加一个可以删除多个视频的方法

    4.1、service_vod服务

    1、控制层

    //根据id删除多个阿里云视频
    @DeleteMapping("/removeBatch")
    public R removeBatch(@RequestParam("videoIdList") List<String> videoIdList){
        vodService.removeMoreVideo(videoIdList);
        return R.ok();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、业务层

    //根据id集合删除多个视频
    @Override
    public void removeMoreVideo(List<String> videoIdList) {
    
        //将集合转换为1,2,3格式
        String str = StringUtils.join(videoIdList.toArray(), ",");
    
        try {
            //初始化对象
            DefaultAcsClient client = initVodClient(accessKeyId, accessKeySecret);
            //创建删除视频request对象
            DeleteVideoRequest request = new DeleteVideoRequest();
            //向request设置要删除视频的id值
            request.setVideoIds(str);
            //调用初始化对象的方法实现删除
            DeleteVideoResponse response = client.getAcsResponse(request);
            log.info("RequestId = " + response.getRequestId() + "\n");
            log.info("批量删除云端视频成功");
        } catch (Exception e) {
            throw new LaptoyException(20001, "视频删除失败");
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3、测试多个视频id是否能删除成功


    4.2、service_edu服务

    1、控制层流程

    @Api(tags = "课程模块")
    @CrossOrigin //解决跨域问题
    @RestController
    @RequestMapping("/eduservice/course")
    public class EduCourseController {
    
    	//课程列表中删除课程方法
    	@DeleteMapping("/removeCourseById/{id}")
    	public R removeCourseById(@PathVariable String id) {
    	    boolean flag = eduCourseService.removeCourse(id);
    	    if (flag) {
    	        return R.ok();
    	    } else {
    	        return R.error();
    	    }
    	}
    }
    
    
    @Service
    public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourse> implements EduCourseService {
    
    	//删除课程
    	@Transactional
    	@Override
    	public boolean removeCourse(String id) {
    	    //1、根据课程id删除小节
    	    eduVideoService.removeVideoByCourseId(id);
    	
    	    ...
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    2、业务层

    @Service
    public class EduVideoServiceImpl extends ServiceImpl<EduVideoMapper, EduVideo> implements EduVideoService {
    
    	// 根据课程id删除小节
    	@Override
    	public void removeVideoByCourseId(String id) {
    	
    	    List<String> list = new ArrayList<>();
    	
    	    QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();
    	    wrapper.eq("course_id", id);
    	
    	    // 向list集合填充待删除视频id
    	    List<EduVideo> eduVideos = this.list(wrapper);
    	    for (EduVideo eduVideo : eduVideos) {
    	        String videoSourceId = eduVideo.getVideoSourceId();
    	        if (!StringUtils.isEmpty(videoSourceId)) {
    	            list.add(videoSourceId);
    	        }
    	    }
    	
    	    // 批量删除所有云端视频
    	    if (list.size() > 0) {
    	        vodClient.removeBatch(list);
    	    }
    	
    	    // 删除所有小节
    	    this.remove(wrapper);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3、新建课程并新建章节小节进行测试,删除课程同时所有云端小节视频应该同时删除


    五、整合Hystrix

    在这里插入图片描述

    当调用远程服务时若远程服务不稳定或者宕机,需要进行降级处理,否则导致链路无法正常运行,这里使用自定义服务降级

    1、service模块POM

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
    <!--hystrix依赖,主要是用 @HystrixCommand -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2、edu模块配置文件添加

    feign:
      hystrix:
        enabled: true
    
    • 1
    • 2
    • 3

    主启动类添加注解

    @EnableHystrix
    
    • 1

    3、远程调用接口实现类

    @Component
    public class VodClientImpl implements VodClient {
        @Override
        public R removeAliyunVideoById(String id) {
            return R.error().message("执行服务熔断器---删除云端视频失败");
        }
    
        @Override
        public R removeBatch(List<String> videoIdList) {
            return R.error().message("执行服务熔断器---批量删除云端视频失败");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4、远程调用接口指定该实现类

    @FeignClient(value = "service-vod", fallback = VodClientImpl.class)
    public interface VodClient {
    
        // 根据视频id删除阿里云视频
        @DeleteMapping("/eduvod/video/removeAliyunVideoById/{id}")
        public R removeAliyunVideoById(@PathVariable("id") String id);
    
        //根据多个视频id删除多个阿里云视频
        @DeleteMapping("/eduvod/video/removeBatch")
        public R removeBatch(@RequestParam("videoIdList") List<String> videoIdList);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    5、优化删除小节业务 - EduVideoServiceImpl

    在这里插入图片描述

    当发生熔断时状态码自然为20001,此时直接抛出自定义异常给前端,作为弹框的错误信息进行展示

    在这里插入图片描述

    6、优化批量删除小节业务 - EduVideoServiceImpl

    在这里插入图片描述


    测试

    添加小节并上传云端视频,停用8003服务

    • 删除小节
      在这里插入图片描述
    • 删除章节
      在这里插入图片描述
  • 相关阅读:
    前端Vue返回顶部[功能]和底部四个角[样式](代源码和详图)
    【LeetCode】415. 字符串相加
    Vue从入门到精通
    PGL图学习之基于UniMP算法的论文引用网络节点分类任务[系列九]
    BI系统有哪些?新手怎么选?
    TinyXML-2介绍
    软考中级软件设计师--1.计算机系统知识
    Methods and Interfaces Part3
    【Vue2】VantUI项目-基础入门02
    TCP/IP协议簇包含的协议
  • 原文地址:https://blog.csdn.net/apple_53947466/article/details/124994731