Springcloud实战:开发课程查询功能

举报
长路 发表于 2022/11/28 20:11:29 2022/11/28
【摘要】 文章目录前言项目模块预览完整项目数据库spring-cloud-course-practice(总模块)eurake-server(服务中心服务)course-service(课程模块)course-list(课程服务)course-price(课程价格服务)course-zuul(网关服务) 前言 本篇博客是在SpringCloud的实战案例,若文章中出现相关问题,请指出! 所有博客文件目录索引

@[toc]

前言

本篇博客是在SpringCloud的实战案例,若文章中出现相关问题,请指出!

所有博客文件目录索引:博客目录索引(持续更新)

案例demo地址:Gitee-demoexer/SpringCloud/01、springcloud课程列表开发GitHub-javademos/SpringCloud/01、springcloud课程列表开发

项目模块预览

image-20211005101458879

一般我们做项目使用的springboot,但是一旦项目做的大了之后,服务功能越做越多就会导致代码冗余,可能一个服务中提供了多项功能,可能导致越到后面就会出现单个工程项目越来越大,代码冗余的情况;并且集群部署时,可能一个服务提供了多项功能导致大量的请求来临到某个服务。

基于种种原因出现了微服务,微服务指的是将原本的大的服务模块进行拆分,例如订单模块、日志模块、基础数据模块等等等,每一个模块都是服务,服务与服务之间也能够进行相互调用,下面我介绍一下springcloud中每个组件的功能及出现的目的:

最原始阶段:后台管理服务、前台服务、小程序服务,后台管理提供给用户后台管理的功能,前台负责数据展示的功能,小程序提供一些小程序需要的功能
	问题:后台管理服务到之后也会涉及很多的功能模块,若是不进行拆分,后台管理做的很大时就会不利于代码扩展与编写等等导致冗余等情况,其他部分也是如此
springcloud搭建微服务
——————1、搭建一个服务中心服务
首先微服务需要有一个服务中心(Eureka Server),对应的服务在启动时都能够进行注册到服务中心上去。
	服务中心为之后远程调用、网关统一鉴权都提供了很大的便利
————————2、改造基本服务为eureka client
有了服务中心,接着我们需要将我们的服务注册到服务中心上去,如何注册呢?就需要将我们的原本服务改造为Eureka client并进行配置服务中心地址,当服务启动时就会自动注册到服务中心。
————3、引入openfeign,让服务具有远程调用的功能
注册好以后,其实我们某个服务可能需要去调用其他远程服务的接口,此时急需要在eureka client中引入openfeign,编写feign client接口来进行远程调用。
————4、解决远程可能会出现的问题,引入Hystrix
能够远程调用了,此时就会出现问题,因为远程调用难免会出现一系列的问题如调用的服务瘫痪,功能不可用情况,如何解决呢?springcloud也给我们提供了一个组件断路器Hystrix,其能够在我们调用远程服务出现不可避免的问题时返回默认内容,根据我们需求自己定义。
————5、实现鉴权等功能,引入Zuul
此时我们的服务中心已经初步具备管理多个节点功能,此时我们又出现了一个需求就是对应的服务也不能够被人随意访问,那么就需要对我们的服务提供保护措施,此时需要有一个统一的鉴权服务,Zuul出现了,我们想要访问某个服务中得接口可以统一通过zuul网关来进行访问,在zuul中我们可以通过设置过滤器来实现一些特定的功能。
————6、负载均衡,Ribbon
在3中引入openfeign具有调用远程服务接口的能力,一般的话远程服务不会独有一份,可能有多个相同节点服务,如何解决大量请求会去调用远程服务时的选择策略,springcloud提供了一个Ribbon组件,其包含三个策略用于我们进行远程调用服务的选择等等

总而言之:要想把大的服务模块进行拆分,拆分为多个微服务并且服务与服务之前进行相互调用就会面临一系列的问题,springcloud组织给出了一系列的解决方案,每个组件都有其存在的意义,都能够解决相对应的痛点。



完整项目

本次项目:主要就是两个服务,一个服务提供课程列表的功能,另一个服务提供课程价格的功能,通过这两个简单服务来整合springcloud,进行学习springcloud中的六个组件。

数据库

image-20211005105144222

一个是课程表、另一个是课程价格表,前者与后者是一对多的关系。

/*
 Navicat Premium Data Transfer

 Source Server         : 本地mysql5.7
 Source Server Type    : MySQL
 Source Server Version : 50732
 Source Host           : localhost:3306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 50732
 File Encoding         : 65001

 Date: 05/10/2021 10:51:03
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for course
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course`  (
  `id` int(11) NOT NULL,
  `course_id` int(11) NULL DEFAULT NULL,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `valid` int(1) NULL DEFAULT NULL COMMENT '是否上架,0不上架,1上架\r\n',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES (1, 362, 'Java并发核心知识体系靖江', 1);
INSERT INTO `course` VALUES (2, 409, '玩转Java并发工具,精通JUC', 1);
INSERT INTO `course` VALUES (3, 121, 'Nginx入门到实践', 0);

-- ----------------------------
-- Table structure for course_price
-- ----------------------------
DROP TABLE IF EXISTS `course_price`;
CREATE TABLE `course_price`  (
  `id` int(11) NOT NULL,
  `course_id` int(11) NULL DEFAULT NULL,
  `price` decimal(10, 2) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of course_price
-- ----------------------------
INSERT INTO `course_price` VALUES (1, 362, 348.50);
INSERT INTO `course_price` VALUES (2, 409, 399.68);
INSERT INTO `course_price` VALUES (3, 121, 266.78);

SET FOREIGN_KEY_CHECKS = 1;


spring-cloud-course-practice(总模块)

image-20211005105453227

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!--  模块化管理  -->
    <packaging>pom</packaging>
    <modules>
        <module>course-service</module>
        <module>eurake-server</module>
        <module>course-zuul</module>
    </modules>
    <!-- 父模块   -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.changlu</groupId>
    <artifactId>spring-cloud-course-practice</artifactId>
    <version>1.0.0</version>
    <name>spring-cloud-course-practice</name>
    <description>course project for Spring Cloud</description>

    <properties>
        <java.version>1.8</java.version>
        <mybatis.plus.version>3.4.3</mybatis.plus.version>
        <mysql-version>8.0.23</mysql-version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <!--  表示Spring Cloud的版本-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql-version}</version>
            </dependency>
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus-boot-starter</artifactId>
                <version>${mybatis.plus.version}</version>
            </dependency>
            <!--       SpringCloud指定版本     -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR5</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


eurake-server(服务中心服务)

image-20211005105657407

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-course-practice</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>eurake-server</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <!-- 模块名及描述信息 -->
    <name>course-eureka-server</name>
    <description>Spring Cloud Eureka</description>
    <dependencies>
        <!-- 服务中心依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

EurekaServerApplication.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @ClassName EurakeServerApplication
 * @Author ChangLu
 * @Date 2021/10/4 13:42
 * @Description 服务中心服务
 */
@EnableEurekaServer   //开启Eureka Server服务
@SpringBootApplication
public class EurekaServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

application.yaml

server:
  port: 8000
spring:
  application:
    name: eureka-server  # 应用名称

eureka:
  instance:
    hostname: localhost  
  client:
    fetch-registry: false  #fetch-registry:获取注册表。不需要同步其他节点数据。(当前没有建立eureka server集群,这里不需要同步节点)
    register-with-eureka: false  # 代表是否将自己也注册到Eureka Server,这里不注册
    service-url:  # 设置服务中心的地址  => http://localhost:8000/eureka/
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

此时我们访问服务中心:http://localhost:8000/



course-service(课程模块)

image-20211005110008976

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-course-practice</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>

    <groupId>com.changlu</groupId>
    <artifactId>course-service</artifactId>

    <!-- 管理两个服务 -->
    <modules>
        <module>course-list</module>
        <module>course-price</module>
    </modules>

</project>


course-list(课程服务)

image-20211005110238065

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.changlu</groupId>
        <artifactId>course-service</artifactId>
        <version>1.0.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.changlu</groupId>
    <artifactId>course-list</artifactId>
    <version>1.0.0</version>
    <name>course-list</name>
    <description>course list</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>test</scope>
        </dependency>
        <!--    Eureka-client:用于注册到服务中心    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

application.yaml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  application:
    name: course-list   # 应用名

server:
  port: 8080

# 指定注册的服务中心地址,一般与eureka-server中配置的对应,此时该服务启动就会将自己注册到服务中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/

# 被course-price调用并设置ribbon,所以这里要开启
ribbon:
  eureka:
    enabled: true

启动器:

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.changlu.democourse.mapper")
public class CourseListApplication {

    public static void main(String[] args) {
        SpringApplication.run(CourseListApplication.class, args);
    }

}

controller、service、mapper一系列

@Data
public class Course implements Serializable {

    private static final long serialVersionUID = -6849794470748667710L;

    private Integer id;
    private Integer courseId;
    private String name;
    private Integer valid;
}


/**
 * @ClassName CourseController
 * @Author ChangLu
 * @Date 2021/10/4 13:03
 * @Description 课程控制器
 */
@RestController
@RequestMapping("/course")
public class CourseController {

    @Autowired
    private CourseService courseService;

    @GetMapping("/list")
    public List<Course> getList(){
        return  courseService.getCourseList();
    }

}

public interface CourseService {
    List<Course> getCourseList();
}

@Service
public class CourseServiceImpl implements CourseService {

    @Autowired
    private CourseMapper courseMapper;

    @Override
    public List<Course> getCourseList() {
        return courseMapper.getCourseList();
    }
}


@Repository
public interface CourseMapper {

    @Select("select * from course")
    List<Course> getCourseList();

}

该服务提供了查询课程的能力,该服务启动时将会被注册到服务中心。



course-price(课程价格服务)

image-20211005110819815

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.changlu</groupId>
        <artifactId>course-service</artifactId>
        <version>1.0.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.changlu</groupId>
    <artifactId>course-price</artifactId>
    <version>1.0.0</version>
    <name>course-price</name>
    <description>springcloud demo for course-price</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--    远程调用:feign    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--    引入断路器模块    -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--   引入包含pojo模块,解决client的报错问题     -->
        <dependency>
            <groupId>com.changlu</groupId>
            <artifactId>course-list</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yaml:

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  application:
    name: course-price   # 应用名

server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/

# 开启负载均衡
#ribbon:
#  eureka:
#    enabled: true

# 服务id=>命名空间=>配置属性
course-list:   # 当前远程调用的服务application名
  ribbon:
    NFLoadBanlancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule  # 轮询策略

# 开启断路器
feign:
  hystrix:
    enabled: true

client目录中远程调用及断路器实现类:

/**
 * @ClassName CourseListClient
 * @Author ChangLu
 * @Date 2021/10/4 16:36
 * @Description 远程调用
 */
@FeignClient(value = "course-list",fallback = CourseListClientHystrix.class)
@Primary
public interface CourseListClient {

    @GetMapping("/course/list")
    List<Course> getList();

}

/**
 * @ClassName CourseListClientHystrix
 * @Author ChangLu
 * @Date 2021/10/4 20:30
 * @Description 断路器,对于服务不可用或其他情况进行统一的返回值返回
 */
@Component
public class CourseListClientHystrix implements CourseListClient{

    @Override
    public List<Course> getList() {
        Course course = new Course();
        course.setId(0);
        course.setCourseId(0);
        course.setName("Java从入门到精通");
        course.setValid(0);
        return Collections.singletonList(course);
    }

}

启动器:

@SpringBootApplication
@MapperScan("com.changlu.courselist.mapper")
@EnableFeignClients
@EnableCircuitBreaker    //打开断路器
public class CoursePriceApplication {

    public static void main(String[] args) {
        SpringApplication.run(CoursePriceApplication.class, args);
    }

}

pojo、controller、service汇总

//pojo
@Data
public class CoursePrice implements Serializable {

    private static final long serialVersionUID = -6849794470748667710L;

    private Integer id;
    private Integer courseId;
    private BigDecimal price;

}
/**
 * @ClassName CourseAndPrice
 * @Author ChangLu
 * @Date 2021/10/5 7:15
 * @Description TODO
 */
@Data
public class CourseAndPrice extends Course implements Serializable {

    private static final long serialVersionUID = -6855794470748667710L;

    private BigDecimal price;
}

//controller
@RestController
@RequestMapping("/courseprice")
public class CoursePriceController {

    @Autowired
    private CoursePriceService coursePriceService;
    //远程调用动态代理类注入
    @Autowired
    private CourseListClient courseListClient;

    @GetMapping("/list/{id}")
    public CoursePrice getList(@PathVariable("id")Integer id){
        return  coursePriceService.getCoursePriceByCourseId(id);
    }

    @GetMapping("/test")
    public List<Course> testFeignCourseService(){
        return courseListClient.getList();
    }

    @GetMapping("/courseprice")
    public List<CourseAndPrice> getAllCourseAndPrice(){
        return coursePriceService.getAllCourseAndPrice();
    }

}

//service
public interface CoursePriceService {

    /**
     * 根据课程id查询到课程价格
     * @param courseId
     * @return
     */
    CoursePrice getCoursePriceByCourseId(Integer courseId);

    /**
     * 查询出所有的课程及价格
     * @return
     */
    List<CourseAndPrice> getAllCourseAndPrice();
}
@Service
public class CoursePriceServiceImpl implements CoursePriceService {

    @Autowired
    private CoursePriceMapper coursePriceMapper;
    @Autowired
    private CourseListClient courseListClient;

    @Override
    public CoursePrice getCoursePriceByCourseId(Integer courseId) {
        return coursePriceMapper.selectOne(new LambdaQueryWrapper<CoursePrice>()
                .eq(CoursePrice::getCourseId,courseId)
        );
    }

    @Override
    public List<CourseAndPrice> getAllCourseAndPrice() {
        //远程调用课程服务,查询出所有的课程
        List<Course> courses = courseListClient.getList();
        List<CourseAndPrice> newCourses = new ArrayList<>(courses.size());
        if(!CollectionUtils.isEmpty(courses)){
            for (Course course : courses) {
                CourseAndPrice courseAndPrice = new CourseAndPrice();
                BeanUtils.copyProperties(course, courseAndPrice);
                //本地查询
                CoursePrice price = this.getCoursePriceByCourseId(course.getCourseId());
                courseAndPrice.setPrice(price.getPrice());
                newCourses.add(courseAndPrice);
            }
        }
        return newCourses;
    }
}

//mapper
public interface CoursePriceMapper extends BaseMapper<CoursePrice> {
}

该服务注册到服务中心,并且进行了远程调用course-list模块、断路器实现以及负载均衡ribbon。



course-zuul(网关服务)

image-20211005111542303

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>spring-cloud-course-practice</artifactId>
        <groupId>com.changlu</groupId>
        <version>1.0.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>course-zuul</artifactId>

    <dependencies>
        <!--    用于服务注册     -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--    zuul网关     -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.yaml

spring:
  application:
    name: zuul-gateway

server:
  port: 9000

# 指定注册的服务中心地址,一般与eureka-server中配置的对应,此时该服务启动就会将自己注册到服务中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka/

# zuul的相关配置
zuul:
  prefix: /changlu   # 访问zuul网关的前缀url(由原来的/ => /changlu)
  routes:            # 路由配对,下面有两组服务
    course-list:
      path: /list/**             # 2、指定的服务路由转换 (例如由原来的/course-list => /list)
      service-id: course-list    # 1、指定的服务名(application name):课程服务
    course-price:
      path: /price/**
      service-id: course-price

启动器:

/**
 * @ClassName ZuulGatewayApplication
 * @Author ChangLu
 * @Date 2021/10/5 8:27
 * @Description 网关启动类
 */
@EnableZuulProxy
@SpringCloudApplication
public class ZuulGatewayApplication {

    public static void main(String[] args) {
        SpringApplication.run(ZuulGatewayApplication.class,args);
    }
}

两个过滤器:用于进行拦截请求前、后

/**
 * @ClassName PreRequestFilter
 * @Author ChangLu
 * @Date 2021/10/5 9:26
 * @Description 前置请求过滤器
 */
@Component
public class PreRequestFilter extends ZuulFilter {
    @Override
    public String filterType() {
        //过滤器类型
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //过滤器顺序
        return 0;  //0-1000 从小到大顺序依次执行,这里表示第一个执行
    }

    @Override
    public boolean shouldFilter() {
        return true;  //是否启动过滤器
    }

    //具体过滤器中执行的方法
    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        currentContext.set("startTime",System.currentTimeMillis());
        System.out.println("前缀过滤器pre已经记录时间");
        return null;
    }
}

/**
 * @ClassName PostRequestFilter
 * @Author ChangLu
 * @Date 2021/10/5 9:31
 * @Description 后置请求处理器
 */
@Component
public class PostRequestFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    /**
     * filter执行顺序,值越小优先级越高
     * 官方推荐使用x-1方式优先排序
     * @return
     */
    @Override
    public int filterOrder() {
        return FilterConstants.SEND_RESPONSE_FILTER_ORDER-1;  //响应过滤器为1000,这里-1表示该过滤器越优先执行
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext currentContext = RequestContext.getCurrentContext();
        Long startTime = (Long) currentContext.get("startTime");
        Long duration = System.currentTimeMillis() - startTime;
        String uri = currentContext.getRequest().getRequestURI();
        System.out.println("uri:"+uri+",处理时长为:"+duration);
        return null;
    }
}

设置好网关之后,我们可以通过网关来进行访问我们的服务:

# 第一个是课程服务的一个接口;第二个是课程价格的接口,该接口中包含了远程调用课程服务
http://localhost:9000/changlu/list/course/list    
http://localhost:9000/changlu/price/courseprice/courseprice
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。