微服务入门(Nacos,Feign,网关Zuul)

一 、Nacos

1.1前期准备

下载地址https://github.com/alibaba/nacos/releases

Window目录下找到bin文件夹进入cmd命令行 Startup.cmd -m standalone

在浏览器上访问: http://localhost:8848/nacos/ (登录页面: 默认的账号和密码都是nocas , 登录成功)

1.2简化项目实例准备

注意:父工程中使用了Nacos的依赖时,子工程中在有用的时候Erureka的依赖时需要注释掉

实例sql数据库

📎dubbo-demo.sql

<?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">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.example</groupId>
  <artifactId>springcloud</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <modules>
    <module>service_productor</module>
    <module>service_user</module>
    <module>service_order</module>
    <module>service_productor/product_mapper</module>
    <module>service_productor/product_pojo</module>
    <module>service_productor/product_service</module>
    <module>service_productor/product_utils</module>
    <module>service_productor/product_</module>
  </modules>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <!--统一的版本-->
    <mysql.version>5.1.47</mysql.version>
    <mybatis-spring>2.1.1</mybatis-spring>
    <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
  </properties>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.2</version>
    <relativePath/>
  </parent>

  <!--只启动声明作用,不导入jar-->
  <dependencyManagement>
    <dependencies>
      <!--maven项目默认是单继承
      Scope的其他参数如下:(可以回去之前的一个图)
      compile:默认的scope,表示 dependency 都可以在生命周期中使用。
      而且,这些dependencies 会传递到依赖的项目中(子项目中)。适用于所有阶段,会随着项目一起发布
      provided:跟compile相似,但是表明了dependency 由JDK或者容器提供,
      例如Servlet AP和一些Java EE APIs。这个scope 只能作用在编译和测试时,同时没有传递性,
      即:child module(传递到子模块中)无法引用。
      runtime:表示dependency不作用在编译时,但会作用在运行和测试时,如JDBC驱动,适用运行和测试阶段,
      与provided相反。
      test:表示dependency作用在测试时,不作用在运行时。
      只在测试时使用,用于编译和运行测试代码。不会随项目发布。
      system:跟provided 相似,但是在系统中要以外部JAR包的形式提供,maven不会在repository查找它。

      补充: Maven默认是单继承,无法做多继承,上面有一个parent 继承了springBoot项目
      如果在实际开发中,用户需要多个parent?
      dependencyManagement   type   pom
      org.springframework.cloud   dependencyManagement 配置到进来 ===>其实就是变相的继承
      -->
      <!--            <dependency>-->
      <!--                <groupId>org.springframework.cloud</groupId>-->
      <!--                <artifactId>spring-cloud-dependencies</artifactId>-->
      <!--                <version>${spring-cloud.version}</version>-->
      <!--                <type>pom</type>-->
      <!--                <scope>import</scope>-->
      <!--            </dependency>-->

      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.5.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <dependency> <!--子工程就不需要写版本-->
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
        <!--                <scope></scope>-->
      </dependency>
      <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>${mybatis-spring}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </dependency>
  </dependencies>


</project>
<?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>springcloud</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>service_user</artifactId>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>


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

    <dependency> <!--子工程就不需要写版本-->
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>

    <!--        <dependency>-->
    <!--            <groupId>org.springframework.cloud</groupId>-->
    <!--            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>-->
    <!--        </dependency>-->

    <!--nacos的客户端-->
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

  </dependencies>

</project>
<?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>springcloud</artifactId>
    <groupId>org.example</groupId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>service_order</artifactId>

  <properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
  </properties>

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

    <dependency> <!--子工程就不需要写版本-->
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
    </dependency>

    <!--        <dependency>-->
    <!--            <groupId>org.example</groupId>-->
    <!--            <artifactId>servcie_user</artifactId>-->
    <!--            <version>1.0-SNAPSHOT</version>-->
    <!--        </dependency>-->
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

  </dependencies>

</project>

1.3Nacos基本使用

1.3.1注册服务

server:
  port: 8080
spring:
  application:
    name: service-order
  datasource:
    url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: anhui #集群名称
     #  namespace: 36f5279d-6bf5-42b9-a09e-5452449ac5ae #名字重复(微服务,空间大)   用的自动生成的ID
      # ephemeral: false # 设置非临时实例
server:
  port: 9090
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/dubbo-demo?useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: user-service
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: anhui

注意:上述的父类依赖有冲突修改为下

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.3.9.RELEASE</version>
  <relativePath/>
</parent>

最后在启动这两个服务

1.3.2显示效果

微服务的大多数组件是相互独立,使用的大概率不相互影响

可以直接在idea这里配置来覆盖配置文件内容

-Dserver.port=9092 -Dspring.cloud.nacos.discovery.cluster-name=Beijing

二.负载均衡

不在有任何操作的提前下--->依然是轮询的形式去调用服务(所有集群所有服务)

@Bean
@LoadBalanced   //可以实现负载均衡
public RestTemplate restTemplate(){
    return new RestTemplate();
}

在order中做了一个配置cluster-name: anhu===>默认的ZoneAvoidanceRule 并不能实现根据同集群的来实现负载

spring:
  application:
    name: service-order
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: anhui #集群名称
     #  namespace: 36f5279d-6bf5-42b9-a09e-5452449ac5ae #名字重复(微服务,空间大)   用的自动生成的ID
      # ephemeral: false # 设置非临时实例
user-service:
  ribbon: #负载均衡的规则
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule  # 负载均衡规则
ribbon: # 和你使用 nacos还是 eureka
  eager-load:
    enabled: true #开启饿汉模式    一个是用到再去加载,一个是提前加载好
    clients: #指定饿汉服务
      - user-service

补充:

---->配置权重 有的服务器性能好--->多访问 性能差---->少访问

默认情况NacosRule是同集群内随机挑选,不会考虑机器的性能;====>设置权重,权重越大访问频率越高 0-1之间

三、环境隔离

Nacos提供nameSpace来实现环境的隔离

  1. 提供很多的namespace
  2. 每一个nameSpace里面有group  service等------>不同namespace之间是服务相互不可见

3.1步骤

3.1.1创建空间

3.1.2把对应的服务放进到对应的空间中

因为不在同一个命名空间下,所以调用不到userServcie

四.实例的类型

  • 临时的实例 : 如果服务器宕机一段时间,自动从我们的列表中剔除,默认类型
  • 非临时的实例: 如果服务器宕机一段时间,不会从列表中剔除,可以叫做永远的实例
spring:
  application:
    name: service-order
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: anhui #集群名称
      #  namespace: 36f5279d-6bf5-42b9-a09e-5452449ac5ae #名字重复(微服务,空间大)   用的自动生成的ID
      ephemeral: false # 设置非临时实例

总结: eureka 和nacos共同的作用 ===>服务注册,服务拉取出来,心跳机制

区别: 1 . eureka没有永久实例
2.Nocas服务的主动检测(永远实例),  临时实例两者是一样的---->心跳模式
3. eureka 不会主动,nocas主动推送服务,服务更新及时,服务状态相对准确
4. 集群有区别  Nocos 集群默认AP方式,临时的实例采用cp  eureka 全部AP

五、Nacos的配置管理

5.1统一的配置管理

调用的别人服务的服务,如果需要去改一些配置,从项目中配置文件是很繁琐

5.1.1nacos中配置

5.1.2获取配置文件的过程

spring:
  application:
    name: userservice
  profiles:
    active: dev   #环境
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml    #文件后缀名

5.1.3具体操作步骤

5.1.3.1导包
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
方法一: 在去@Value的类上面添加注解@RefreshScope方法一: 在去@Value的类上面添加注解@RefreshScope
package com.chenbuting.controller;

import com.chenbuting.pojo.User;
import com.chenbuting.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
@RefreshScope
public class UserController {

    @Value("${pattern.dateformat}")
    private String patternDataformat;

    @GetMapping("/data")
    public String getDate(){
        return patternDataformat;
    }
}
错误点注意:

方式二:使用注解 @ConfigurationProties
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "pattern") //属性的注入
public class Ptconfig {
    //定义很多的属性值
    private String dataformat;
}
package com.chenbuting.controller;

import com.chenbuting.config.Ptconfig;
import com.chenbuting.pojo.User;
import com.chenbuting.service.UserService;
import jdk.nashorn.internal.ir.annotations.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@RestController
@RequestMapping("/user")
//@RefreshScope
public class UserController {

    @Autowired
    private Ptconfig ptconfig;

    @GetMapping("/data")
    public Ptconfig getDate(){
        return ptconfig;
    }
}

5.2多环境

5.2.1一个服务有多个配置

启动项目的多个配置文件 如application.yml application-dev.yml application-test.yml

只会去找默认,不带后缀的 项目的下的配置同样的多环境配置是一样的

5.2.2多个微服务公用一个配置文件

spring:
  application:
    name: userservice
  profiles:
    active: dev   #环境
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml    #文件后缀名
        namespace: dc9c11f6-af82-4c4f-bd99-65027a4baa6f
        extension-configs:
          - data-id: common.yaml
  #        shared-configs: #共享多配置文件 多个
  #          - dataId: common.yaml

六、服务调用 Feign

package com.chenbuting.service;

import com.chenbuting.mapper.OrderMapper;
import com.chenbuting.pojo.Order;
import com.chenbuting.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    //    @Bean
    //    @LoadBalanced   //可以实现负载均衡
    //    public RestTemplate restTemplate(){
    //        return new RestTemplate();
    //    }

    // 传统的方式
    //    @Autowired
    //    private UserService userService;
    //
    //    public Order findById(Long id){
    //        Order order = orderMapper.findByID(id);
            Long userId =  order.getUserId();
            User user = userService.userFindByID(id);
             order.setUser(user);
    //        return   order;
    //    }

    //方法一 :  HTTP
    public Order findById(Long id){
        Order order = orderMapper.findByID(id);
        Long userId =  order.getUserId();
        //发送http请求    实体引入的问题?
        //User user =  restTemplate.getForObject("http://localhost:9090/user/"+userId, User.class);
        //User user =  restTemplate.getForObject("http://localhost:9999/user/"+userId, User.class);

        //Eureka 取服务的规则?  服务名称,获取实例列表,工具实例取完成负载
        User user = restTemplate.getForObject("http://user-service/user/"+userId, User.class);

        order.setUser(user);
        return order;
    }

}

1. 代码的可读性质太差了,编程体验很差

2. 微服务被各种复杂的调用,URL维护起来很麻烦, ==>地址 参数 返回值

Http ---->客户端Feign 声明式的http客户端,可以解决上面的问题;

使用的时候: Feign 属于 spring cloud

Nacos 属于spring Alibaba cloud====>混用

6.1基本使用

6.1.1 导包

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

6.1.2 声明(没有具体)我要用的东西 ---->按照接口文档

UserSerevice --->findByID()

预期结果

6.2 Spring Cloud 使用 FeignClient 启动报错(问题)

类似的报错信息

Description:

Field orderService in com.chenbuting.controller.OrderController required a bean of type 'com.chengbuting.feignClient.UserClinet' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'com.chengbuting.feignClient.UserClinet' in your configuration.

我们这两个的关键配置

import com.chengbuting.pojo.User;

@FeignClient("userservice")
public interface UserClinet {
    @GetMapping("user/{userId}")
    public User userById(@PathVariable("userId") Long id);
}
package com.chenbuting;

@SpringBootApplication
@MapperScan("com.chenbuting.mapper")
@EnableFeignClients
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}

@Bean
@LoadBalanced   //可以实现负载均衡--->默认的轮询
public RestTemplate restTemplate(){
return new RestTemplate();
};
}

从表面上看配置并没有什么问题,那么我们来分析一下问题的具体原因。

注解 @EnableFeignClients 与 @ComponentScan 有冲突,两种注解都会搜索注入指定目录中的 bean 。@EnableFeignClients 引入了 FeignClientsRegistrar 类,实现了 Spring 的bean 资源的加载。

FeignClientsRegistrar中registerFeignClients方法获取了@EnableFeignClients注解中的basepackage 属性值,并进行注入。如果两种注解都使用时,其中@EnableFeignClients会覆盖 @ComponentScan 中指定的目录,从而恢复到默认目录。

问题解决方式:

1、可以将 FeignClient 这个 bean 放在和 Application 启动类同级目录

2、可以在 @EnableFeignClients中通过 clients 属性指定 bean 目录

@EnableFeignClients(clients = {
        UserClinet.class
})

所以service_order的启动类的总体修改为

@SpringBootApplication
@MapperScan("com.chenbuting.mapper")
@EnableFeignClients(clients = {
        UserClinet.class
})
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class,args);
    }

    @Bean
    @LoadBalanced   //可以实现负载均衡--->默认的轮询
    public RestTemplate restTemplate(){
        return new RestTemplate();
    };

//    @Bean
//    public IRule randomRule(){
//        return new RandomRule();
//    }
}

6.3 Fegin的一些参数

#feign:
#  client:
#    config:
#      userservcie: #只对这个服务生效
#        logger-level: FUll #日志级别
feign:
client:
config:
default: #全局生效
logger-level: BASIC #日志级别

6.4 Fegin的优化

Feign底层发起http请求,依赖于其它的框架。其底层客户端实现包括:

  • URLConnection:默认实现,不支持连接池
  • Apache HttpClient :支持连接池
  • OKHttp:支持连接池

因此提高Feign的性能主要手段就是使用连接池代替默认的URLConnection。
这里我们用Apache的HttpClient来演示。

1) 引入依赖

<!--httpClient的依赖 -->
<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-httpclient</artifactId>
</dependency>

2) 配置连接池

在模块的application.yml中添加配置:

#feign:
#  client:
#    config:
#      userservcie: #只对这个服务生效
#        logger-level: FUll #日志级别

feign:
  client:
    config:
      default: # default全局的配置
        loggerLevel: BASIC # 日志级别,BASIC就是基本的请求和响应信息
  httpclient:
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数
    max-connections-per-route: 50 # 每个路径的最大连接数

3) 总结,Feign的优化

  1. 日志级别尽量用basic
  2. 使用HttpClient或OKHttp代替URLConnection
  • 引入feign-httpClient依赖
  • 配置文件开启httpClient功能,设置连接池参数

6.5 Feign最佳实践

所谓最近实践,就是使用过程中总结的经验,最好的一种使用方式。

自习观察可以发现,Feign的客户端与服务提供者的controller代码非常相似:
feign客户端:

Controller:

简化这种重复的代码

1)继承方式

一样的代码可以通过继承来共享:

  1. 定义一个API接口,利用定义方法,并基于SpringMVC注解做声明。
  2. Feign客户端和Controller都集成该接口。

优点:

  • 简单
  • 实现了代码共享

缺点:

  • 服务提供方、服务消费方紧耦合
  • 参数列表中的注解映射并不会继承,因此Controller中必须再次声明方法、参数列表、注解

2)抽取方式(大多情况)

将Feign的Client抽取为独立模块(新建一个module项目),并且把接口有关的POJO、默认的Feign配置都放到这个模块中,提供给所有消费者使用。例如,将UserClient、User、Feign的默认配置都抽取到一个feign-api包中,所有微服务引用该依赖包,即可直接使用

在feign-api中然后引入feign的starter依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

然后,把模块中中编写的FeignClien客户端、实体类、配置类都复制到feign-api项目中,把这一个安装到maven仓库,那里用,就直接导入即可

在模块中中使用feign-api

在模块的pom文件中中引入feign-api的依赖:

<dependency>
    <groupId>cn.itcast.demo</groupId>
    <artifactId>feign-api</artifactId>
    <version>1.0</version>
</dependency>
#### 4)解决扫描包问题
方式一:

指定Feign应该扫描的包:
在启动类上

@EnableFeignClients(basePackages = "cn.feign.clients")

方式二:

在启动类上

指定需要加载的Client接口:

@EnableFeignClients(clients = {UserClient.class})

七、 网关

Gateway 服务网关、nacos(集群)配置管理_nacos gateway_lqh12138的博客-CSDN博客

目前能和spring cloud体系紧密集成的有两种API网关:zuul(zuul1)和spring cloud gateway

所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服 务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控(黑白名单)、路由转发等等。

核心逻辑: 路由转发+执行过滤器链

7.1 zuul与gateway的简单对比

7.2 gateway的简单使用

1)依赖导入

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

  <!--依赖nacos发现服务-->
  <dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  </dependency>
</dependencies>

2)application.yml文件的配置

server:
  port: 10001
spring:
  application:
    name: gateWay
  cloud:
    nacos:
      server-addr: localhost:8848
    gateway:
      routes: #配置路由  --->那些服务加入网关
       - id: user-service  #路由器的id,自定义  #唯一
         uri: lb://userservice #路由的目标地址, lb负载均衡 后面跟上服务的名称
         predicates: #路由的断言,就是你符合不符合我路由的规则的条件
           - Path=/user/**
       - id:  service-order
         uri: lb:// serviceorder
         predicates:
           - Path=/order/**
         filters: #过滤器
           - AddRequestHeader=Truth,hello Word #添加消息头
    #跨域 精确允许跨域  方法   跨域的检测时间

执行过程

测试结果

断言

3)过滤器 GateWayFilte

过滤器: 当前路由下面的过滤器 默认的过滤器 全局过滤器(默认1,依次增加)

默认的过滤器 >当前路由下面的过滤器 >全据过滤器

Order值越小,优先级别越高, order值一样的,遵循上面的顺序

全局过滤器

全局过滤器作用于所有路由, 无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。

内置全局过滤器

SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理如下:

过滤器的工厂 --->添加一些配置(接近40个)

简单案例

简单的权限 --->有参数 anthor 为并且admin 同时满足,否则拦截

过滤的顺序

过滤代码

//@Order(-1)
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    //请求和响应   Request  Response
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //一个请求里面有多个参数  Key value  Map    auth
        ServerHttpRequest request  =  exchange.getRequest();
        MultiValueMap<String, String>  params = request.getQueryParams();
        String auth = params.getFirst("auth");
        if("admin".equals(auth)){
            //放行
            return  chain.filter(exchange);
        }
        //拦截下来  ===>实际开发中,会加入自己获得状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();

    }

    @Override
    public int getOrder() {
        return -1;
    }
}

测试结果

7.3 网关如果涉及到跨域问题(固定配置)

spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求 
              - "http://localhost:8090"
              - "http://www.xxx.com"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期 

7.4 限流(了解,后续补充)

  • 45
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈步汀

我的房子靠你了

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值