基于微服务架构的视频上传项目(一)

start from 2021年12月23日11:53:20 to

1.项目介绍

  • P2-19:42,项目整体开发流程。P2-1:20:05,后台管理系统admin-dist/前台管理系统api-dist,启动方法:对应文件夹cmd,npm install -g(表示全局安装) anywhere。1:27:31,启动后端界面连接网关进行请求交互,去后端打包之后进入admin-dist/js/app.js处修改网关接口。

1-1.后台系统开发

  1. 后端功能:1.类别增删改查、2.用户列表(用户查询/模糊查询)、3.视频列表(视频列表/模糊查询)、4.后台管理员登录,退出。
  2. 技术选型: SpringBoot + SpringCloud + Vue + Docker(nacos/mysql........)
  3. 后台项目结构:
  • yingxue-admin =====> 维护后端系统全局父项目
  • yingxue-commons =====> 用来存放后端系统公共代码工具类....
  • yingxue-users =====> 用来完成用户列表
  • yingxue-category =====> 用来完成类别接口
  • yingxue-videos =====> 用来完成视频接口
  • yingxue-admin =====> 用来完成后端管理员操作
  • yingxue-gateway =====> 后端系统网关服务,路由转发+跨域处理:localhost:8888/9999
  • 后端管理系统页面:用vue+elementui完成
  1. 环境搭建:1)库表入库、2)构建项目结构、3)每个微服务构建一个独立springboot应用、4)启动nacos 将每个应用作为微服务注册到nacos、5)创建服务网关 配置对应路由规则 + 跨域、6)根据接口文档开发接口,连接对应数据:json,postman、6)启动后端界面连接网关进行请求交互,去后端打包之后admin-dist/js/app.js修改网关接口。

1-2.虚拟机上安装相应的镜像

  • 删除不需要的镜像,比如:docker rmi -f centos:7
  • 安装镜像:docker pull nacos/nacos-server:2.0.2
  • 创建双网卡的步骤P3-8:09:

创建双网卡.png 更改IPV4地址.png

  • 进入虚拟机,找到网络配置:cd /etc/sysconfig/network-scripts/,ls本来会看到有两块网卡,一个叫ens33,ens37。但没有ens37配置文件,所以要拷贝:cp ifcfg-ens33 ifcfg-ens37,接下来编辑ens37配置文件:vi ifcfg-ens37,修改DEVICE=ens37NAME=ens37,删除UUID,修改:BOOTPROTO=static,在最下面添加:IPADDR=10.15.0.2,不能和上面第二张图中的IP地址(10.15.0.2)一样。保存退出并重启network:systemctl restart network

1-3.新建父项目

  • 小技巧:安装JetBrainsToolbox自动下载更新IDEA。
  • 新建一个yingxue-admin父项目:Save-Actions插件:选择General-》Activate save actions on save …… ②Formatting-Actions -》Reformat file。删除父项目的src文件夹。维护:①维护springboot父项目、②维护springcloud和springcloud-alibaba版本

父项目配置文件pom.xml

<groupId>com.jun</groupId>
<artifactId>yingxue-admin</artifactId>
<version>1.0</version>

<!--properties属性可以自定义n多个属性-->
<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
    <spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version>
    <mybatis.spring.boot.starter.version>2.1.3</mybatis.spring.boot.starter.version>
    <mysql.connector.java.version>5.1.38</mysql.connector.java.version>
    <druid.vcerion>1.2.1</druid.vcerion>
    <commons.fileupload.version>1.4</commons.fileupload.version>
    <javacpp.version>1.4.1</javacpp.version>
    <javacv.version>1.4.1</javacv.version>
    <opencv.platform.version>3.4.1-1.4.1</opencv.platform.version>
    <ffmpeg.platform.version>3.4.2-1.4.1</ffmpeg.platform.version>
    <aliyun.java.sdk.core.version>4.5.3</aliyun.java.sdk.core.version>
    <commons.lang.version>2.6</commons.lang.version>
    <fastjson.version>1.2.74</fastjson.version>
    <spring.data.redis.version>2.3.0.RELEASE</spring.data.redis.version>
    <aliyun.sdk.oss.version>3.10.2</aliyun.sdk.oss.version>
</properties>

<!--继承SpringBoot父项目-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.5.RELEASE</version>
</parent>
<!--维护SpringCloud和SpringCloud-alibaba-->
<dependencyManagement> <!--父项目中只维护依赖-->
    <dependencies>
        <!--引入SpringCloud-alibaba-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>${spring.cloud.alibaba.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--引入SpringCloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--mysql,mybatis,druid-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.connector.java.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.boot.starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.vcerion}</version>
        </dependency>
    </dependencies>
</dependencyManagement>

1-4.新建子模块

  • 除了commons以外,每个模块都是系统中的一个微服务,每个服务都是一个独立的应用(SpringBoot应用)。新建的微服务都会向服务注册中心nacos进行注册:P3-40:54,IDEA连接远程Linux。然后创建一个yingxue文件夹,将docker-compose.yml文件放到该文件夹里。启动:[root@192 yingxue]# docker-compose up -d,启动起来后可以查看日志:docker logs -f 容器id,然后在浏览器中输入:192.168.200.130:8848/nacos

①yingxue-commons

  • 主要用来放一些公共的工具类和一些公共的代码,公共的依赖。

pom.xml

<dependencies>
    <!--web-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--nacos-client-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

②yingxue-administrators

启动mysql并初始化数据

  • 启动数据库并初始化数据:P4-3:06,原来是用docker启动mysql,然后创建数据库,执行SQL脚本。现在启动docker-mysql的时候,让其自动创建数据库yingxue,自动执行sql脚本。P4-6:19。docker run --rm(创建一个临时的mysql,容器关闭它就自动删除了) -d -e MYSQL_ROOT_PASSWORD=root mysql:5.6,然后进入mysql容器:docker exec -it 容器id bash,切换目录:cd docker-entrypoint-initdb.d,日后只需要这个目录里面有sql文件就行了。所以完整的通过docker启动mysql的语句是:docker run --name mysql01 -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=yingxue -v data:/var/lib/mysql -v ./yingxue.sql:/docker-entrypoint-initdb.d/yingxue.sql mysql:5.6,但项目中还是用docker-compose up -d启动的较多:
volumes:
  data:
services:
# P4-10:50 将yingxue.sql上传到Linux的/root/yingxue目录下,并更新该文件夹下的docker-compose.yml
# 随后执行:[root@192 yingxue]# docker-compose up -d,连接mysql查看表以及数据库是否创建成功。
  mysql:
    image:
      mysql:5.6
    ports:
      - "3306:3306"
    networks:
      - yingxue_network
    volumes:
      - data:/var/lib/mysql
      - ./yingxue.sql:/docker-entrypoint-initdb.d/yingxue.sql
    environment:
      - "MYSQL_ROOT_PASSWORD=hrj"
      - "MYSQL_DATABASE=yingxue"

登录的接口

  • 用PostMan测试:

截图_20211326011335.png

已登录-用户信息的接口

//2.已登录用户信息的接口,P6-5:00
    @GetMapping("/admin-user")
    public Admin admin(String token) {
        log.info("当前的token信息:{}", token);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return (Admin) redisTemplate.opsForValue().get(token);
    }

截图_20212926072916.png

  • 从上图中可以看到null属性,null属性不再建议向前端打印,因为JSON数据越小,网络传输速度越快。所以返回数据可以不为Admin,可以定义其他对象,比如定义一个Map。但在前后端分离的开发中,大多是重新定义一个dto
//com.jun.dto.AdminDTO.java
public class AdminDTO {
    //@JsonFormat //用来修改转换日期的时间格式的。
    @JsonProperty("name") 
    //代表转换到JSON中的属性名是谁?如果不写,默认就是定义的成员变量名
    private String username;
    private String avatar;……}
//-----com.jun.controller.AdminController.java-------    
//2.已登录用户信息的接口,P6-5:00。//vo=view object(业务返回的结果和页面想要的数据结果不一致,
//所以要把业务的结果转变成一个页面所需要的对象),在前后端分离的开发中,叫做:dto=data transfer object
@GetMapping("/admin-user")
public AdminDTO admin(String token) {
    log.info("当前的token信息:{}", token);
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    Admin admin = (Admin) redisTemplate.opsForValue().get(token);
    AdminDTO adminDTO = new AdminDTO();
    //1.属性复制:P6-15:42
    BeanUtils.copyProperties(admin, adminDTO); //将两个对象中重复的属性拷贝
    //adminDTO.setName(admin.getUsername()); //如果在AdminDTO中,name属性改为username,并且加了@JsonProperty就可以省略。
    return adminDTO;
}

截图_20215726105743.png

登出的接口

//3.登出的接口
@DeleteMapping("/tokens/{token}")
public void logout(@PathVariable("token") String token) {
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    redisTemplate.delete(token);
}

截图_20211926111913.png

网关中的配置

gateway:
      routes: # 用来配置路由规则:id、uri、path P3-56:39
        - id: admins_router
          uri: lb://API-ADMINS       # http://localhost:8980 # 日后可能是集群,所以不能写死58:38
          predicates:
            - Path=/admins/demos,/admins/tokens,/admins/admin-user,/admins/tokens/**
          filters: #P3-1:05:01
            - StripPrefix=1  #去掉请求前缀的filter,后边需要写一个int类型的数字,1代表一级,2代表去掉两级

③yingxue-category

类别列表的接口

截图_20211327011301.png

  • P8-14:42

截图_20214227014254.png

<resultMap type="com.jun.entity.Category" id="CategoriesMap">
    <result property="id" column="id" jdbcType="INTEGER"/>
    <result property="name" column="name" jdbcType="VARCHAR"/>
    <!--封装children,p8-16:20-->
    <collection property="children" javaType="list" ofType="com.jun.entity.Category">
        <id property="id" column="cid" jdbcType="INTEGER"/>
        <result property="name" column="cname" jdbcType="VARCHAR"/>
        <result property="parentId" column="cparentId"/>
    </collection>
</resultMap>
<!--查询类别,一级类别父ID没值。P8-14:42-->
<select id="queryByFirstLevel" resultMap="CategoriesMap">
    select c.id, c.name, c1.id cid, c1.name cname, c1.parent_id cparentId
    from yingxue.category c
             left join yingxue.category c1
                       on c.id = c1.parent_id
    where c.parent_id is null;
</select>
//1.类别列表
@GetMapping
public List<Category> categories() {
    return categoryService.queryByFirstLevel();
}

类别更新的接口

//com.jun.controller.CategoryController.java
//2.修改列表接口
@PatchMapping("/{id}")
public Category update(@PathVariable("id") Integer id, @RequestBody Category category) {
    log.info("更新类别的id:{}", id);
    log.info("更新类别的信息:{}", JSONUtils.writeJSON(category));
    //更新:P9-7:13
    category.setId(id);
    return categoryService.update(category);
}

类别添加的接口

类别添加的接口.png

//3.添加类别的接口 com.jun.controller.CategoryController.java
@PostMapping
public Category save(@RequestBody Category category) {
    log.info("添加类别的信息:{}", JSONUtils.writeJSON(category));
    return categoryService.insert(category);
}

//com.jun.service.impl.CategoryServiceImpl.java
@Override
public Category insert(Category category) {
    Date date = new Date();
    category.setCreatedAt(date);
    category.setUpdatedAt(date);
    this.categoryDao.insert(category);
    return category;//返回的Category是否存在id?
}
<!--新增所有列,useGeneratedKeys针对于mysql数据库可用,使用数据自动递增id;
    keyProperty将数据库本次生成的id赋值给参数对象的哪个属性。-->
<insert id="insert" parameterType="com.jun.entity.Category" keyProperty="id" useGeneratedKeys="true">
    insert into category(name, parent_id, created_at, updated_at, deleted_at)
    values (#{name}, #{parentId}, #{createdAt}, #{updatedAt}, #{deletedAt})
</insert>

后端系统的结合接口测试

  • 上传admin-dist文件夹到项目的根目录,Ctrl+f搜localhost,baseURL:"http://localhost:9999/admin"而此时我们的网关地址为:

网关的配置

server:
  port: 9999
spring:
  application:
    name: API-GATEWAY
  cloud:
    nacos:
      server-addr: 192.168.200.130:8848
    gateway:
      routes: # 用来配置路由规则:id、uri、path P3-56:39
        - id: admins_router
          uri: lb://API-ADMINS       # http://localhost:8980 # 日后可能是集群,所以不能写死58:38
          predicates:
            - Path=/admins/demos,/admins/tokens,/admins/admin-user,/admins/tokens/**
          filters: #P3-1:05:01
            - StripPrefix=1  #去掉请求前缀的filter,后边需要写一个int类型的数字,1代表一级,2代表去掉两级

        # category router
        - id: category_router
          uri: lb://API-CATEGORY
          predicates: # P8-9:31
            - Path=/category/demos,/category/categories,/category/categories/**
          filters:
            - StripPrefix=1

        # videos router
        - id: videos_router
          uri: lb://API-VIDEOS
          predicates:
            - Path=/videos/demos
          filters:
            - StripPrefix=1

        # users router
        - id: users_router
          uri: lb://API-USERS
          predicates:
            - Path=/users/demos
          filters:
            - StripPrefix=1
      globalcors: #跨域配置处理  P3-1:10:28
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
  • 启动admin-dist,先切换到目录下:cd admin-dist,然后启动(P1-1:21:13):anywhere -p 9091(端口随便写),P12-3:00 。推荐好用的图床:路过图床。
  • 全局安装:D:\笔记\青橙小店\SpringCloud&Alibaba微服务综合实战项目\资料\admin-dist>npm install -g anywhere

截图_20210828030807.png

④yingxue-users

⑤yingxue-videos

⑥yingxue-gateway

  • 网关底层默认集成的是ribbon,ribbon是负载均衡的客户端。P3-1:03:26,介绍网关。Gateway=router路由+filter过滤

猜你喜欢

转载自juejin.im/post/7123350338395963428