【微服务全家桶】-实用篇-1-SpringCloud

【微服务全家桶】-实用篇-1-SpringCloud


1 导学

1.1 微服务定义

微服务是一种经过良好架构设计的分布式架构方案

微服务特征:

(1)单一职责(2)面向服务(3)自治:团队独立,技术独立,数据独立(4)隔离性强

1.2 微服务技术对比

在这里插入图片描述

1.3 认识微服务

在这里插入图片描述

SpringCloud和SpringBoot需要兼容

在这里插入图片描述

1.4 服务拆分注意事项

在这里插入图片描述

1.5 服务远程调用Demo-基于RestTemplate

(1)注册RestTemplate

在order-service中的OrderApplication中注册RestTemplate

@SpringBootApplication  
public class OrderApplication {  
    public static void main(String[] args) {  
        SpringApplication.run(OrderApplication.class, args);  
    }  
    @Bean  
    public RestTemplate restTemplate() {  
        return new RestTemplate();  
    }  
}  

(2)在Service中注入RestTemplate

(3)调用其方法,GET用getForObject,POST用postForObject,并封装

public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;
    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        //2.利用RestTemplate发起http请求,查询用户
        String url = "http://userservice/user/" + order.getUserId();
        User user= restTemplate.getForObject(url, User.class);
        //3.封装user到order中
        order.setUser(user);
        // 4.返回
        return order;
    }
} 

2 Eureka

2.1 提供者与消费者

在这里插入图片描述

2.2 Eureka基本原理

在这里插入图片描述

2.3 Eureka的实现

在这里插入图片描述

2.3.1 搭建注册中心

(1)引入依赖

引入spring-cloud-starter-netflix-eureka-server的依赖,要修改eureka-server模块的pom中maven的版本,降到8,JDK版本1.8

(2)编写启动类

编写启动类EurekaApplication,添加注解***@EnableEurekaServer@SpringBootApplication***

@EnableEurekaServer  
@SpringBootApplication  
public class EurekaApplication {  
    public static void main(String[] args) {  
        SpringApplication.run( EurekaApplication.class, args );  
    }  
} 
(3)添加application.yml文件
server:  
  port: 10086  
spring:  
  application:  
    name: eureka-server  
eureka:  
  client:  
    service-url:  
      defaultZone: http://127.0.0.1:10086/eureka/ 
(4)启动SpringBoot,打开10086端口

在这里插入图片描述

注册到Eureka中的示例,UP表示正常,后面接ip地址

2.3.2 服务注册

将user-service、order-service服务注册到eureka-server中,以order-service为例

(1)在user-service引入依赖

在user-service引入spring-cloud-starter-netflix-eureka-client的依赖

(2)配置application.yml文件
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: 123sjbsjb
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: orderservice
mybatis:
  type-aliases-package: cn.itcast.user.pojo
  configuration:
    map-underscore-to-camel-case: true
logging:
  level:
    cn.itcast: debug
  pattern:
    dateformat: MM-dd HH:mm:ss:SSS
eureka:  
  client:  
    service-url:  
      defaultZone: http://127.0.0.1:10086/eureka/  
(3)启动多个orderApplication类,并添加端口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

添加-Dserver.port=8082,打开Eureka显示注册成功

在这里插入图片描述

2.3.3 服务发现

服务拉取事基于服务名称获取服务列表,然后对服务列表做负载均衡。例子采用order-service完成服务拉取。

(1)修改OrderService的代码

修改OrderService的代码,用服务名替换ip和端口(要与application.yml的服务名称一致)

String url = "http://localhost:8081/user/" + order.getUserId();  
User user= restTemplate.getForObject(url, User.class); 

改为

String url = "http://user-service/user/" + order.getUserId();  
User user= restTemplate.getForObject(url, User.class); 
(2)在order-service的启动类添加负载均衡的注解

在order-service的启动类OrderApplication中的RestTemplate添加负载均衡的注解,负载均衡注解***@LoadBalanced***

@LoadBalanced  
@Bean  
public RestTemplate restTemplate() {  
    return new RestTemplate();  
} 
(3)启动spring

启动spring,依次访问localhost:8080/order/101和localhost:8080/order/102

在这里插入图片描述

在这里插入图片描述

发现已经实现负载均衡

3 Ribbon 负载均衡

3.1 负载均衡流程

在这里插入图片描述

在这里插入图片描述

3.2 负载均衡策略

在这里插入图片描述

3.3 修改负载均衡策略

3.3.1 定义一个新的IRule

在order-service中的OrderApplication中定义一个新的IRule,这是针对全局的设置

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
@EnableFeignClients(defaultConfiguration = FeginClientConfiguration.class)
public class OrderApplication {

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

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

3.3.2 在配置文件中修改规则

在order-service的application.yml中,添加新的规则,只针对某个微服务而言。

userservice:  
  ribbon:  
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule 

3.4 饥饿加载

ribbon默认进行懒加载,第一次访问时才会创建LoadBalanceClient。而修改为饥饿加载则会在项目启动时创建,降低第一次访问的耗时

ribbon:  
  eager-load:  
    enabled: true  
    clients: userservice 

如果有多个clients,-xxservice

ribbon:  
  eager-load:  
    enabled: true  
    clients:  
      - userservice  
      - xxservice 

4 Nacos注册中心

4.1 认识Nacos

Nacos是阿里巴巴的产品,现在是SpringCloud产品的一个组件,比Eureka功能更加丰富

4.1.1 启动nacos

在bin目录下打开cmd,输入命令

startup.cmd -m standalone

在这里插入图片描述

点击console的地址,ctrl+单击

在这里插入图片描述

账号密码均为nacos,成功进入nacos管理后台

在这里插入图片描述

4.2 Nacos注册中心

4.2.1 注册服务到Nacos

(1)在父工程中添加依赖

在cloud-demo的父工程中添加spring-cloud-alibaba的管理依赖

<dependency>  
    <groupId>com.alibaba.cloud</groupId>  
    <artifactId>spring-cloud-alibaba</artifactId>  
    <version>2.2.5.RELEASE</version>  
</dependency>
(2)注释依赖

注释掉order-service和user-service原有的eureka依赖

(3)添加客户端依赖

为order-service和user-service添加nacos的客户端依赖

<dependency>  
    <groupId>com.alibaba.cloud</groupId>  
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>  
    <version>2.2.5.RELEASE</version>  
</dependency> 
(4)修改yml文件

修改order-service和user-service的yml文件

server:  
  port: 8081  
spring:  
  datasource:  
    url: jdbc:mysql://localhost:3306/cloud_user  
    username: root  
    password: 123sjbsjb  
    driver-class-name: com.mysql.cj.jdbc.Driver  
  application:  
    name: userservice  
  cloud:  
    nacos:  
      server-addr: localhost:8848  
(5)启动nacos
startup.cmd -m standalone

点击服务管理-》服务列表

在这里插入图片描述

4.3 Nacos服务分级存储模型

在这里插入图片描述

4.3.1 配置nacos集群

在这里插入图片描述

(1)修改application.yml

为user-service修改application.yml

cloud:  
  nacos:  
    server-addr: localhost:8848  
    discovery:  
      cluster-name: HZ #集群名称 杭州 

启动实例后修改cluster-name,可以实现多集群cluster-name: SH

(2)nacos管理

在这里插入图片描述

(3)为order-service配置

要求order-service优先调用本地的user-service

修改order-service的application.yml,与(2)同理

第一次运行发现各个实例轮询访问,并未实现优先调用,是因为ribbon负载均衡的调用策略是轮询。因此要在order-service中设置负载均衡的IRule为NacosRule,这个规则会优选寻找属于同一集群的服务。

userservice:  
  ribbon:  
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

改为

userservice:  
  ribbon:  
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule  

重启order-service发现没有使用上海集群

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

如果停掉杭州集群,只留上海集群,order-service则会爆出警告

在这里插入图片描述

4.3.2 为集群配置权重

在这里插入图片描述

点击编辑,可以修改其权重

在这里插入图片描述

当权重为0时代表不会访问该实例。这样就可以实现平滑上线。灰度发布,升级迭代后的产品权重值设的较小,放入少量用户测试。

在这里插入图片描述

4.4 Nacos环境隔离

在这里插入图片描述

默认都在命名空间public下,group为默认分组

在这里插入图片描述

点击命名空间,创建新的命名空间

在这里插入图片描述

在这里插入图片描述

生成唯一的uuid命名空间ID,返回服务列表,出现dev的命名空间

在这里插入图片描述

如果想将服务放到命名空间中,则需要在对应服务的application.yml中添加namespace

cloud:  
  nacos:  
    server-addr: localhost:8848  
    discovery:  
      cluster-name: HZ #集群名称 杭州  
      namespace: bcc7eea2-5231-4b3a-9250-4afde546ca27 

现在user-service和order-service已经是两个世界的人,重启order-service。如果想让两个服务能相互访问,则需要放在同一个namespace下。

4.5 Nacos注册中心细节

在这里插入图片描述

4.5.1 设置临时实例和非临时实例

cloud:  
  nacos:  
    server-addr: localhost:8848  
    discovery:  
      cluster-name: SH #集群名称 杭州  
      ephemeral: false #设置非临时实例 

在这里插入图片描述

即使停掉order-service,nacos也不会剔除

在这里插入图片描述

4.6 Nacos与Eureka的对比

在这里插入图片描述

5 Nacos 配置管理

5.1 Nacos实现配置管理

在这里插入图片描述
在这里插入图片描述

发布后

在这里插入图片描述

5.2 微服务配置拉取

在这里插入图片描述

5.2.1 引入Nacos配置管理客户端依赖

为userservice添加配置管理依赖

<dependency>  
 <groupId>com.alibaba.cloud</groupId>  
 <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>  
 <version>2.2.5.RELEASE</version>  
</dependency>  

5.2.2 创建bootstrap.yml文件

在userservice的resource中创建bootstrap.yml

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev #开发环境,这里是dev
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos地址
      config:
        file-extension: yaml # 文件后缀名

删除application.yml中重复的配置

尝试读取配置

在UserController中添加导入配置信息

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

    @Autowired
    private UserService userService;
    @Value("${pattern.dateformat}")
    private String dateformat;
   
    @GetMapping("/now")
    public String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }
}

注意namespace的位置,bootstrap的命名空间要与userservice一致

5.3 实现配置的热更新

Nacos实现热更新有两种方式,配置注入不同,使用的注解也不同

5.3.1 方式一,注解***@RefreshScope***

在@Value注入的变量所在的类中加上注解***@RefreshScope***

在这里插入图片描述

在这里插入图片描述

5.3.2 方式二,使用***@ConfigurationProperties***(推荐)

(1)创建配置类PatternProperties
@Data  
@Component  
@ConfigurationProperties(prefix = "pattern")  
public class PatternProperties {  
    private String dateformat;  
} 
(2)注入PatternProperties

在UserController注入PatternProperties,这里不需要@RefreshScope

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

    @Autowired
    private UserService userService;
//    @Value("${pattern.dateformat}")
//    private String dateformat;
    @Autowired
    private PatternProperties patternProperties;

    @GetMapping("/prop")
    public PatternProperties prop() {
        return patternProperties;
    }
    @GetMapping("/now")
    public String now() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternProperties.getDateformat()));
    }
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }
}

5.4 多环境配置共享

在这里插入图片描述

5.4.1 针对单环境

在nacos中添加userservice.yaml

在这里插入图片描述

在配置类中读取envSharedValue

@Data  
@Component  
@ConfigurationProperties(prefix = "pattern")  
public class PatternProperties {  
    private String dateformat;  
    private String envSharedValue;  
}  

在UserController中读取

@GetMapping("/prop")  
    public PatternProperties prop() {  
        return patternProperties;  
    } 

5.4.2 修改实例环境

在这里插入图片描述

重启服务,8081可以读取到dev的环境变量,而8082则读取不到

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5.4.3 配置优先级

在这里插入图片描述

5.5 Nacos 集群搭建

5.5.1 搭建数据库,初始化数据库表结构

5.5.2 下载Nacos,配置Nacos

(1)修改conf下cluster.conf.example改成cluster.conf

(2)在cluster.conf下#example下添加ip和端口

127.0.0.1:8845      
127.0.0.1.8846      
127.0.0.1.8847 

(3)修改application.properties下文件,添加数据库配置

spring.datasource.platform=mysql           
db.num=1          
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC      
db.user.0=root      
db.password.0=123sjbsjb   

(4)复制nacos文件三份,分别命名1/2/3,并分别修改各自application.properties,修改server.port为8845/8846/8847

(5)分别启动nacos节点 startup.cmd

(6)nginx做反向代理,修改nginx下conf/nginx.conf文件,加入nginx下http中,将nacos的server等监听端口加入

upstream nacos-cluster {      
    server 127.0.0.1:8845;      
    server 127.0.0.1:8846;      
    server 127.0.0.1:8847;      
}         
server {      
    listen       80;      
    server_name  localhost;        
    location /nacos {      
        proxy_pass http://nacos-cluster;      
    }      
}    

(7)修改userservice下的application.yml或bootstraps.yml文件

spring:    
  cloud:    
    nacos:    
      server-addr: localhost:80 # Nacos地址

6 Http客户端Feign

Feign都是基于调用者的,即orderservice

6.1 RestTemplate调用

代码可读性差,编程体验不统一

参数复杂,URL难以维护

6.2 定义和使用Feign客户端

6.2.1在orderservice中引入依赖

<!-- feign http配置-->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

6.2.2 开启Feign功能,@EnableFeignClients

在orderservice的启动类中添加注释,开启Feign功能,@EnableFeignClients

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

6.2.3 编写Feign的客户端,@FeignClient

在orderservice中创建clients定义接口UserClient,@FeignClient

@FeignClient(value = "userservice")    
public interface UserClient {    
    
    @GetMapping("/user/{id}")    
    User findById(@PathVariable("id") Long id);    
}   

6.2.4 改造OrderService

将原有的使用url调用的restTemplate改造

public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
    /*@Autowired
    private RestTemplate restTemplate;*/
    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        /*//2.利用RestTemplate发起http请求,查询用户
        String url = "http://userservice/user/" + order.getUserId();
        User user= restTemplate.getForObject(url, User.class);*/
        //2.利用Feign发起http请求,查询用户
        User user = userClient.findById(order.getUserId());
        //3.封装user到order中
        order.setUser(user);
        // 4.返回
        return order;
    }
}

Feign包含ribbon,自动对客户端进行负载均衡

在这里插入图片描述

6.3 Feign的自定义配置

在这里插入图片描述

6.3.1 方式一 配置文件方式

修改orderservice的application.yml文件

(1)全局生效

feign:    
 client:    
  config:    
   default:    
     loggerLevel: FULL 

(2)局部生效

-使用default就默认全局,userservice指定服务名就针对某个微服务

feign:    
 client:    
  config:    
   userservice:    
     loggerLevel: FULL 

6.3.2 Java代码配置方式

(1)先声明一个Bean
public class FeginClientConfiguration {
    @Bean
    public Logger.Level loglevel() {
        return Logger.Level.BASIC;
    }
}
(2)全局配置,@EnableFeignClients

如果是全局配置,则把他放到orderservice的启动类@EnableFeignClients这个注解中

@EnableFeignClients(defaultConfiguration = FeignClientConfiguration.class)  
(3)局部配置,@FeignClient

如果是局部配置,则把他放到自定义接口UserClient的@FeignClient注解中

@FeignClient(value = "userservice",configuration = FeignClientConfiguration.class)    

6.4 Feign性能调优

6.4.1 Feign连接池配置

Feign连接池配置,为Feign添加HttpClient支持

(1)引入HttpClient依赖
<!-- feign的httpclient的连接池配置-->
<dependency>
	<groupId>io.github.openfeign</groupId>
	<artifactId>feign-httpclient</artifactId>
</dependency>
(2)配置连接池
feign:
  client:
    config:
      default:  #default全局配置
        loggerLevel: BASIC #日志级别,BASIC基本请求和相应信息
  httpclient:
    enabled: true # 支持HttpClient的开关
    max-connections: 200 # 最大连接数
    max-connections-per-route: 50 # 单个路径的最大连接数

6.5 Feign的最佳实践

6.5.1 方式一 继承

给消费者的FeignClient和提供者的Controller定义统一的父接口作为标准

在这里插入图片描述

6.5.2 方式二 抽取

将FeignClient抽取为独立模块,并且把接口有关的POJO、默认的Feign配置都放在这个模块中,提供给所有消费者使用

在这里插入图片描述

6.5.3 方式二 实现

步骤

(1)创建一个module,命名feign-api,然后引入feign的starter依赖

    <dependencies>
        <!-- feign http配置-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!-- feign的httpclient的连接池配置-->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
    </dependencies>

(2)将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目中

在这里插入图片描述

(3)在order-service中引入feign-api的依赖

		<!--引入fegin-api依赖 -->
        <dependency>
            <groupId>com.itheima</groupId>
            <artifactId>feign-api</artifactId>
            <version>1.0</version>
        </dependency>

(4)修改order-service中所有与上述三个组件有关的import部分,改成导入feign-api中的包

(5)重启测试

解决报错

发现orderservice报错,找不到UserClient

在这里插入图片描述

分析原因,spring的自动配置只能扫描当前启动类下的包,因此OrderApplication扫描不到feign-api下的UserClient

当定义的FeignClient不在SpringBootApplication的扫描包的范围时,这些FeignClient无法使用,提供两种解决方式

(1)指定FeignClient所在包

注解@EnableFeignClients指定参数basePackages包所在位置

@EnableFeignClients(defaultConfiguration = FeginClientConfiguration.class,basePackages = "cn.itcast.feignapi.clients")

(2)指定FeignClient的字节码

@EnableFeignClients(defaultConfiguration = FeginClientConfiguration.class,client)

多个字节码用{}进行包裹

7 Gateway 网关

7.1 认识网关

在这里插入图片描述

SpringCloud中网关的实现包括两种:gateway(响应式编程)和zuul(阻塞式)

7.2 搭建网关

7.2.1 创建模块,引入依赖,创建启动类

创建新的module,引入SpringCloudGateway的依赖和nacos的服务发现依赖

    <dependencies>
        <!-- Nacos服务发现依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
        <!-- Spring Cloud Gateway依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>

添加启动类GatewayApplication

@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        // 启动SpringBoot应用
        SpringApplication.run(GatewayApplication.class, args);
    }
}

7.2.2 编写路由配置及naocs地址

路由配置包括:路由id,路由目标uri,路由断言predicates,路由过滤器filters

server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**

7.2.3 服务细节

在这里插入图片描述

7.3 断言工厂

配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断条件

在这里插入图片描述

7.4 路由过滤器GatewayFilter

GatewayFilter是网关中提供的一种过滤器,可以对进入网关的请求和微服务返回的响应做处理

在这里插入图片描述

在这里插入图片描述

7.4.1 路由过滤器

添加请求头

- id: user-service # 路由id,自定义,只要唯一即可
  # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
  uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
  predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
    - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
  filters:
    - AddRequestHeader=Truth, Itcast is freaking awesome! # 这个是添加请求头,可以添加多个

在userservice中验证,打开userservice的controller,添加参数

    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id,
                          @RequestHeader(value="Truth",required = false) String truth) {
        System.out.println("truth = " + truth);
        return userService.queryById(id);
    }

重启userservice和gateway

在这里插入图片描述

7.4.2 默认过滤器

default-filters: 默认过滤器

spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
      default-filters: # 这个是默认过滤器,所有的路由都会经过这个过滤器
        - AddRequestHeader=Truth,Itcast is freaking awesome! # 这个是添加请求头,可以添加多个

7.4.3 全局过滤器

全局过滤器GlobalFilter的作用也是处理一切进入网关的请求和微最务响应,与GatewayFilter的作用一样。

区别在于GatewayFilter通过配置定义,处理逻辑是固定的。而GlobalFilter的逻辑需要自己写代码实现。

定义方式是需要实现GlobalFilter接口

//@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1.获取请求参数
        ServerHttpRequest request = exchange.getRequest();
        MultiValueMap<String, String> params = request.getQueryParams();
        //2.获取参数中的authorization参数
        String auth = params.getFirst("authorization");
        //3.判断authorization是否有效
        if("admin".equals(auth)){
            //4.有效,放行
            return chain.filter(exchange);
        }
        //5.如果无效,拦截
        //5.1.设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
        return exchange.getResponse().setComplete();
    }

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

@Component注解把AuthorizeFilter注入到Spring中作为一个Bean对象,AuthorizeFilter类实现GlobalFilter, Ordered两个接口及其方法。

GlobalFilter其方法 public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)exchange.getRequest()获取请求头,request.getQueryParams()获取请求参数,

params.getFirst("authorization")获取第一个匹配key=authorization的value,

chain.filter(exchange)是放行到下一个过滤器链,如果拦截到了,先设置状态码401HttpStatus.UNAUTHORIZEDexchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);。再进行拦截exchange.getResponse().setComplete()

Ordered也可以通过注解来设置过滤器顺序@Order(-1)也可以通过重写方法来实现。

重启spring

地址中‘?’之后的部分就是通过GET发送的请求数据,各个数据之间用‘&’符号隔开。

在这里插入图片描述

没有authorization则拒绝访问401

7.5 过滤器顺序

在这里插入图片描述
在这里插入图片描述

7.6 跨域问题处理

跨域:域名不一致就是跨域,主要包括:

域名不同:www.taobao.com和www.taobao.org和www.jd.com和miaosha.jd.com

域名相同,端口不同:localhost:8080和localhost:8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS

网关处理跨域问题也是采用CORS方案

7.6.1 跨域问题测试

安装live-server npm install live-server -g

将index.html启动起来,live-server --port=8090,显示CORS禁止跨域访问

在这里插入图片描述

将配置导入gateway的application.yml中

spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/**
#      default-filters: # 这个是全局过滤器,所有的路由都会经过这个过滤器
#        - AddRequestHeader=Truth,Itcast is freaking awesome! # 这个是添加请求头,可以添加多个
      globalcors: # =================》全局的跨域处理《==========================
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求
              - "http://localhost:8090"
              - "http://www.leyou.com"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

重启

注意浏览器的url为http://127.0.0.1:8090,需要浏览器的url和配置中allowedOrigins的一致!

在这里插入图片描述

  • 43
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AAA码农宝哥.

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值