springcloud

springcloud中文API:https://springcloud.cc/spring-cloud-dalston.html
springcloud中国社区:http://springcloud.cn/
springcloud中文网:https://springcloud.cc/

一.Eureka(注册中心)

1.原理图

在这里插入图片描述

  • Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
  • 提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
  • 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新
  • 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态

2.入门案例

Eureka也是一个独立的服务
这里单独创建Eureka服务

1.创建Eureka服务

在这里插入图片描述
修改项目启动类

package com.register;

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

// 在启动类上添加注解 @EnableEurekaServer 标记这个类是 Eureka服务 启动器
@EnableEurekaServer
@SpringBootApplication
public class EurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServer.class, args);
    }
}
2.Eureka服务配置

启动主程序后发现报错
在这里插入图片描述
只要是因为Eureka服务也是以集群形式存在的(因为Eureka服务也有挂掉的可能),所以Eureka服务要向其他Eureka服务服务注册自己
打开application.properties

server.port=8083
# 这里看源码可知springCloud eureka.client.service-url 接收map参数
# 并且默认添加了一组键值对(defaultZone,http://localhost:8761/eureka),这里对其进行覆盖
# 这里自己向自己进行注册
eureka.client.service-url.defaultZone=http://localhost:8083/eureka
# 向eureka服务注册的服务名
spring.application.name=eureka-server
# 失效剔除
# 有些时候,我们的服务提供方并不一定会正常下线,可能因为内存溢出、网络故障等原因导致服务无法正常工作。Eureka Server需要将这样的服务剔除出服务列表。因此它会开启一个定时任务,每隔60秒对所有失效的服务(超过90秒未响应)进行剔除。
# 可以通过eureka.server.eviction-interval-timer-in-ms参数对其进行修改,单位是毫秒,生产环境不要修改。
# 这个会对我们开发带来极大的不变,你对服务重启,隔了60秒Eureka才反应过来。开发阶段可以适当调整,比如:10秒
eureka.server.eviction-interval-timer-in-ms=60000

这里配置完还会报错,因为是自己注册自己,启动时注册自己,由于自己还没启动完,所以报错

3.服务提供方向Eureka注册服务
  • 服务提供方pom添加依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 服务提供方改造springBoot启动器,增加@EnableDiscoveryClient注解
@EnableDiscoveryClient
@SpringBootApplication
public class UserServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}
  • 修改配置文件application.properties增加
# 向eureka注册服务,如果eureka注册中心存在集群,这里要向每个节点注册
eureka.client.service-url.defaultZone=http://localhost:8083/eureka
# 注意如果有多个相同的服务要注册,这里的名字要一样
spring.application.name=user-service
# 默认情况下每个30秒服务会向注册中心发送一次心跳,证明自己还活着(lease-renewal-interval-in-seconds)。
# 如果超过90秒没有发送心跳,EurekaServer就会认为该服务宕机,会从服务列表中移除(lease-expiration-duration-in-seconds)。
# 这两个值在生产环境不要修改,默认即可,开发环境下两个参数尽量改小
eureka.instance.lease-renewal-interval-in-seconds=30
eureka.instance.lease-expiration-duration-in-seconds=90
4.服务消费方调用服务
  • 服务提供方pom添加依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 服务提供方改造springBoot启动器,增加@EnableDiscoveryClient注解
@EnableDiscoveryClient
@SpringBootApplication
public class UserConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }
}
  • 修改配置文件application.properties增加
# 调用eureka提供的服务
eureka.client.service-url.defaultZone=http://localhost:8083/eureka
spring.application.name=consumer-service
# 服务消费端会定时拉去Eureka Server服务的列表只读备份,然后缓存在本地。并且每隔30秒会重新获取并更新数据。我们可以通过下面的参数来修改:
# 生产环境中,我们不需要修改这个值。
# 但是为了开发环境下,能够快速得到服务的最新状态,我们可以将其设置小一点。
eureka.client.registry-fetch-interval-seconds=30

这里服务消费方也要向eureka注册自己

  • 服务调用示例
package com.consumer.controller;

import com.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;

@RestController
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/consumer/{username}")
    public User hello(@PathVariable String username){
        // 根据服务id去eureka查找服务
        List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
        // 从服务list中取出一个 instance
        ServiceInstance serviceInstance = instances.get(0);
        // 从服务中取出ip,port
        String host = serviceInstance.getHost();
        int port = serviceInstance.getPort();
        // 拼接请求地址
        User user = restTemplate.getForObject( "http://"+ host + port + "/service/" + username, User.class);
        return user;
    }
}

3.高可用的Eureka Server

Eureka Server即服务的注册中心,EurekaServer也可以是一个集群,形成高可用的Eureka中心。

多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。

  • 1)搭建Eureka Server集群
    同上,只需要再创建一个Eureka Server,application.properties中配置如下
# 这里两个Eureka Server直接port各不相同
server.port=8084
# 这里要两个 Eureka Server 相互注册
eureka.client.service-url.defaultZone=http://localhost:8083/eureka
# 由于是集群,提供相同的服务,因此服务名一样
spring.application.name=eureka-server
  • 2)服务提供方的注册配置要改
    application.properties
# 向eureka注册服务,这里要向所有的 Eureka Server 注册
eureka.client.service-url.defaultZone=http://localhost:8083/eureka,http://localhost:8084/eureka
spring.application.name=user-service
  • 3)服务调用方的注册配置要改
    application.properties
# 调用eureka提供的服务,这里要向所有的 Eureka Server 注册
eureka.client.service-url.defaultZone=http://localhost:8083/eureka,http://localhost:8084/eureka
spring.application.name=consumer-service

二.Ribbon(负载均衡)

1.简介

Ribbon 是 Netflix 发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为。为Ribbon配置服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多的负载均衡算法,例如轮询,随机等。当然,我们也可以为Ribbon实现自定义的负载均衡算法。

2.示例

  • 1)在上面示例的基础上,再创建一个服务
  • 2)在服务消费方的pom文件中引入Ribbon的依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
  • 3)服务调用方调用代码修改
    HttpClientConfig.java
    增加 @LoadBalanced 注解
package com.consumer.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class HttpClientConfig {

    @Bean // 向容器中添加 RestTemplate
    @LoadBalanced // 添加 @LoadBalanced 注解,实现负载均衡
    public RestTemplate restTemplate() {

        /**
         *  这里可以选择底层实现(有三种):
         *     HttpClient
         *     OkHttp
         *     JDK原生的URLConnection(默认的)
         */
        // 创建 JDK原生的URLConnection(默认的)
        return new RestTemplate();
    }
}

业务层调用时代码

package com.consumer.controller;

import com.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/{username}")
    public User hello(@PathVariable String username){
        // "http://{serviceId}/service/" + username
        String url = "http://USER-SERVICE/service/" + username;
        // 拼接请求地址
        User user = restTemplate.getForObject(url, User.class);
        return user;
    }
}
  • 4)修改负载均衡算法
    默认的负载均衡算法是轮询
    可以在服务调用方的application.properties配置文件中配置
# 修改默认的负载均衡算法(轮询)
# 格式:服务ID(这个服务id是服务提供方的id).ribbon.NFLoadBalancerRuleClassName=实现类的全类名
# 具体实现类有哪些,可以找com.netflix.loadbalancer.IRule的实现类
user-service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

三.Hystrix(熔断器)

1.概念

Hystix,即熔断器。Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。

  • 雪崩问题
    在这里插入图片描述
  • 解决手段
  • 1)线程隔离
  • 2)服务熔断

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

在这里插入图片描述
正常工作的情况下,客户端请求调用服务API接口:
在这里插入图片描述
当有服务出现异常时,直接进行失败回滚,服务降级处理:
在这里插入图片描述
当服务繁忙时,如果服务出现异常,不是粗暴的直接报错,而是返回一个友好的提示,虽然拒绝了用户的访问,但是会返回一个结果。

2.代码示例

  • 1)服务调用方的pom文件引入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 2)服务调用方的启动程序上添加注解@EnableCircuitBreaker
package com.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
// 下面这个三个注解可以由 @SpringCloudApplication 注解代替
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class UserConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }
}
  • 3)服务调用方的调用代码修改
package com.consumer.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class HelloController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 添加 @HystrixCommand 注解
     * 开启线程隔离,服务降级处理,并指定调用失败的方法
     * 1.@HystrixCommand 注解,加在方法上,单独给不同的方法指定不同的降级处理函数(fallbackMethod = "helloFallback" 属性指定失败处理函数)
     *                      要求:原方法和降级处理方法的参数,返回值类型要一致
     *
     * 2.如果想给类中的所有方法指定同一个降级处理函数:
     *              在类上加:@DefaultProperties(defaultFallback = "helloFallback")
     *                              在方法上加:
     *              在要熔断的方法上加:@HystrixCommand
     *              注意:  helloFallback方法不能写参数了,且各个方法的返回值类型要统一
     *
     * hystrix判断服务调用方,调用服务,如果超过1s(默认的),没有得到结果,则启动服务降级,执行Fallback方法
     * 也可以在 application.properties 配置全局的 服务熔断降级超时时间
     * (    配置示例
     *      # 配置全局的服务熔断降级超时时间
     *      hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000
     *      # 指定某个服务熔断降级超时时间(user-service:为服务id)
     *      hystrix.command.user-service.execution.isolation.thread.timeoutInMilliseconds=2000
     * )
     * 由于不同业务执行时间各不相同,有的业务执行时间长,因此需要单独调整没个业务的执行超时时间
     * 通过 @HystrixCommand -> commandProperties -> @HystrixProperty(name = "", value = "")
     * name:execution.isolation.thread.timeoutInMilliseconds, value:时长(毫秒)
     */
    @GetMapping("/consumer/{username}")
    @HystrixCommand(fallbackMethod = "helloFallback",
        commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "2000")
        }
    )
    public String hello(@PathVariable String username){
        // "http://{serviceId}/service/" + username
        String url = "http://USER-SERVICE/service/" + username;
        // 拼接请求地址
        String user = restTemplate.getForObject(url, String.class);
        return user;
    }

    /**
     * 调用失败后调用的方法
     * 要求:参数和返回值类型要和原方法一致
     */
    public String  helloFallback(String username){
        return username + " 不好意思,服务器太拥挤了!";
    }
}
  • 4)服务调用方的配置文件修改
# 配置全局的服务熔断降级超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000

# 指定某个服务熔断降级超时时间(user-service:为服务id),这个配置如果在上面调用方法上配置了,则这里就不用配置
# hystrix.command.user-service.execution.isolation.thread.timeoutInMilliseconds=2000

四.Feign

在前面的学习中,我们使用了Ribbon的负载均衡功能,大大简化了远程调用时的代码:

String baseUrl = "http://user-service/user/";
User user = this.restTemplate.getForObject(baseUrl + id, User.class)

如果就学到这里,你可能以后需要编写类似的大量重复代码,格式基本相同,无非参数不一样。有没有更优雅的方式,来对这些代码再次优化呢?

这就是我们接下来要学的Feign的功能了。

1.简介

Feign(伪装的意思)
Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。主要用于服务调用方

2.使用

  • 1)在服务调用方导入pom依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

由于feign内部包含了RestTemplate,因此向ioc容器中注入RestTemplate的配置可以删除,如下:

package com.consumer.config;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class HttpClientConfig {

    @Bean // 向容器中添加 RestTemplate
    @LoadBalanced // 添加 @LoadBalanced 注解,实现负载均衡
    public RestTemplate restTemplate() {

        /**
         *  这里可以选择底层实现(有三种):
         *     HttpClient
         *     OkHttp
         *     JDK原生的URLConnection(默认的)
         */
        // 创建 JDK原生的URLConnection(默认的)
        return new RestTemplate();
    }
}
  • 2)在服务调用方启动类上添加注解@EnableFeignClients
package com.consumer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class UserConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class, args);
    }
}
  • 3)编写接口
package com.consumer.client;

import com.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * 接口反应出以下信息
 *      1.请求的方式
 *      2.请求的路径
 *      3.请求的参数
 *      4.返回的结果
 */
@FeignClient("USER-SERVICE") //指定服务名称
public interface CustomerClient {
    @GetMapping("/service/{username}")
    User hello(@PathVariable String username);
}
  • 4)调用方法编写
package com.consumer.controller;

import com.consumer.client.CustomerClient;
import com.consumer.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {
    
    // 直接注入 CustomerClient 即可
    @Autowired
    CustomerClient customerClient;

    @GetMapping("/consumer/{username}")
    public User hello(@PathVariable String username){
        // 调用 customerClient 的 hello 方法
        User user = customerClient.hello(username);
        return user;
    }
}
  • 5)使用Feign需要编写的配置
    由于引入 Feign 之后 ,Feign 内部自带hystrix,Ribbon的依赖,这里 hystrix,Ribbon 不是springcloud的,是netflix公司的,
    因此相关配置要重新编写
  • application.properties
# 如果500毫秒连接建立不成功,抛出异常
ribbon.ConnectionTimeOut=1000
# 如果建立连接,超过2000毫秒,服务没有返回结果,抛出异常
ribbon.ReadTimeOut=2000

# hystrix默认是关闭的,首先启用
feign.hystrix.enabled=true

# 开启请求和响应的gzip压缩,以减少通信过程中性能的损耗
feign.compression.request.enabled=true
#  设置压缩的数据类型
feign.compression.request.mime-types=text/html,application/xml,application/json
# 设置触发压缩的大小下限
feign.compression.request.min-request-size=2048
feign.compression.response.enabled=true
  • 在CustomerClient接口,定义Feign的熔断配置
package com.consumer.client;

import com.consumer.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * 接口反应出以下信息
 *      1.请求的方式
 *      2.请求的路径
 *      3.请求的参数
 *      4.返回的结果
 * value 指定服务id
 * fallback 指定服务熔断后的回调函数
 *      fallback 的值 为 class,这个class要实现 CustomerClient 接口
 *      然后在实现类的对应方法写熔断的业务逻辑
 */
@FeignClient(value = "USER-SERVICE", fallback = CustomerClientFallback.class) //指定服务名称
public interface CustomerClient {
    @GetMapping("/service/{username}")
    User hello(@PathVariable String username);
}

  • 在CustomerClientFallback实现类的实现方法中定义Feign的熔断业务逻辑,同时将这个类通过@Component注解注册到spring容器中

五.Zuul网关

在这里插入图片描述
不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。

1.pom文件引入依赖

<!--引入zuul依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--引入eureka-client依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2.配置启动类

package com.gateway;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

3.配置application.properties

server.port=8086

# 配置eureka,注册服务
eureka.client.service-url.defaultZone=http://localhost:8083/eureka,http://localhost:8084/eureka
spring.application.name=gateway-service

# 配置路由规则(请求 和 服务id的对应关系)
# 配置写法
# zuul.routes.服务id=/拦截路径/**
# 外部访问规则:假设原来访问的路径是:/consumer/zxb ,现在通过网关访问:/consumer-service/consumer/zxb
# 由于zuul会自动去eureka上拉取所有服务,进行路由配置,默认将 服务id 和 拦截路径 配置成一样,
# 因此下面内容可以不配置,除非想修改zuul的默认配置
# 但是由于zuul默认会将所有服务进行映射,但是实际情况,有些服务不想对外暴露,
# 可以通过下述配置,将部分服务不做映射
zuul.routes.consumer-service=/consumer-service/**
# user-service服务不做默认映射
zuul.ignoredServices=user-service

# 网关访问前缀,springCloud推荐为 /api
zuul.prefix=/api

4.zuul过滤器介绍

zuul作为网关的其中一个重要功能,就是实现请求的鉴权,而这个动作我们往往是通过zuul提供的过滤器来实现的

  • 1)ZuulFilter介绍
    ZuulFilter是过滤器的顶级父类,在这里我们看一下其中定义的4个重要的方法:
public abstract ZuulFilter implements IZuulFilter{

    abstract public String filterType();// 过滤器类型

    abstract public int filterOrder();// 过滤器优先级
    
    boolean shouldFilter();// 来自IZuulFilter,要不要过滤

    Object run() throws ZuulException;// IZuulFilter,过滤的逻辑
}
  • shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。
  • run:过滤器的具体业务逻辑。
  • filterType:返回字符串,代表过滤器的类型。包含以下4种:
    • pre:请求在被路由之前执行
    • routing:在路由请求时调用
    • post:在routing和errror过滤器之后调用
    • error:处理请求时发生错误调用
  • filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。
  • 2)过滤器执行生命周期
    在这里插入图片描述
  • 正常流程:
    • 请求到达首先会经过pre类型过滤器,而后到达routing类型,进行路由,请求就到达真正的服务提供者,执行请求,返回结果后,会到达post过滤器。而后返回响应。
  • 异常流程:
    • 整个过程中,pre或者routing过滤器出现异常,都会直接进入error过滤器,再error处理完毕后,会将请求交给POST过滤器,最后返回给用户。
    • 如果是error过滤器自己出现异常,最终也会进入POST过滤器,而后返回。
    • 如果是POST过滤器出现异常,会跳转到error过滤器,但是与pre和routing不同的时,请求不会再到达POST过滤器了。

4.zuul的高可用

zuul注册集群,用户直接访问nginx,由nginx转发至zuul集群

5.zuul实现Cors跨域

大家都知道spring boot 可以通过@CrossOrigin实现跨域。但是在spring cloud 里,如果要粒度那么细的去控制跨域,这个就太繁琐了,所以一般来说,会在路由zuul里实现。

实现代码
在zuul服务下添加一个corsFilter实现跨域,实现起来方便。代码如下

@Configuration

public class GateWayCorsConfig {

   @Bean

    public FilterRegistrationBean corsFilter() {

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

        final CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true);

        config.addAllowedOrigin("*");

        config.addAllowedHeader("*");

        config.addAllowedMethod("*");

        //这个请求头在https中会出现,但是有点问题,下面我会说

        //config.addExposedHeader("X-forwared-port, X-forwarded-host"); 

        source.registerCorsConfiguration("/**", config);

        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));

        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);

        return bean;

    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值