SpringCloud Gateway的详细配置

    GateWay是微服务开发中不可或缺的组件之一,为微服务架构的系统提供简单、有效且统一的API路由管理,配有多个服务的项目情况下,可以作为系统的统一入口,提高系统的整体性和统一性。下面根据SpringCloud Alibaba中项目的实际应用,详细说明网关的功能配置。

一、版本与依赖

Springboot版本:2.6.6
SpringCloud版本:2021.0.1
SpringCloud Alibaba版本:2021.1

以下的配置都是按照这些版本来的,不同的版本配置会有一些差异

二、注册中心、配置中心的配置

在yml中配置注册中心、配置中心,我这边选用的是nacos,可以按照自己的项目需求选用注册、配置中心工具

spring:
  application:
    name: demo-gateway
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yml
        shared-configs:
          - application-${
    
    spring.profiles.active}.${
    
    spring.cloud.nacos.config.file-extension}
        refresh-enabled: true
        namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8

三、路由规则设置

1. 关键字说明

id:微服务的ID
uri:微服务对应的目标URL
predicates:断言,根据路径断言路由到对应微服务上

2. 配置示例

spring:
  application:
    name: demo-gateway
  profiles:
    active: dev
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yml
        shared-configs:
          - application-${
    
    spring.profiles.active}.${
    
    spring.cloud.nacos.config.file-extension}
        refresh-enabled: true
        namespace: 45e44563-14eb-4fe1-b5e2-5f7011d0bbb8
    gateway:
      discovery:
        locator:
          enabled: true
      # 路由规则
      routes:
        - id: demo-order
          uri: lb://demo-order
          predicates:
            - Path=/order/**
        - id: demo-member
          uri: lb://demo-member
          predicates:
            - Path=/member/**
        - id: demo-tool
          uri: lb://demo-tool
          predicates:
            - Path=/tool/**

四、网关跨域解决

新增配置类如下:

/**
 * 网关跨域配置
 */
@Configuration
public class GWCrosConfig {
    
    
    @Bean
    public CorsWebFilter corsFilter() {
    
    
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true); // 允许cookies跨域
        config.addAllowedOriginPattern("*");// 放行哪些原始域
        config.addAllowedHeader("*");// #允许访问的头信息,*表示全部
        config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了
        config.addAllowedMethod("OPTIONS");// 允许提交请求的方法类型,*表示全部允许
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);
        return new CorsWebFilter(source);
    }
}

五、网关过滤器的设置

1. 网关过滤器实现

@Component
public class GatewayFilter implements GlobalFilter, Ordered {
    
    

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 网关过滤器进行token拦截
     */
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        //根据配置中心的文件判断是否需要token验证
        if (!ConfigRefresh.tokenEnabled) {
    
    
            return chain.filter(exchange);
        }
        //token非空验证
        List<String> tokenLst = exchange.getRequest().getHeaders().get("token");
        ServerHttpResponse response = exchange.getResponse();
        if (tokenLst == null || tokenLst.size() == 0) {
    
    
            try{
    
    
                DataBuffer buffer = getResBuffer(response, 10001, "token为空,请携带token");
                return response.writeWith(Mono.just(buffer));
            } catch (Exception e) {
    
    
                e.printStackTrace();
                return null;
            }
        }
        //从集合中获取header携带的token
        String token = tokenLst.get(0);
        Long expire = redisTemplate.getExpire(token);
        if (expire > 0) {
    
     //token验证成功
            return chain.filter(exchange);
        } 
        //token验证失败
        try{
    
    
            DataBuffer buffer = getResBuffer(response,10002, "token验证失败");
            return response.writeWith(Mono.just(buffer));
        } catch (Exception e) {
    
    
            return null;
        }
    }

    public int getOrder() {
    
    
        return 0;
    }

    /**
     * 设置拦截之后返回的json
     */
    private DataBuffer getResBuffer(ServerHttpResponse response, int code, String msg) throws Exception {
    
    
        Map<String,Object> respData = new HashMap<String, Object>();
        respData.put("code",code);
        respData.put("msg",msg);
        ObjectMapper objectMapper = new ObjectMapper();
        byte[] bytes = objectMapper.writeValueAsBytes(respData);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        response.setStatusCode(HttpStatus.OK);
        response.getHeaders().add("Content-Type","application/json;charset=UTF-8");
        return buffer;
    }
}

2. 拦截后返回标准json数据

在这里插入图片描述

六、不拦截指定路径设置(针对某个服务)

例如:对tool服务不做过滤拦截

1. 配置不拦截指定路径工厂

@Component
public class IgnoreGlobalFilterFactor extends AbstractGatewayFilterFactory {
    
    

    public IgnoreGlobalFilterFactor() {
    
    
        super(Config.class);
    }

    @Override
    public GatewayFilter apply(Object config) {
    
    
        return this::filter;
    }

    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        exchange.getAttributes().put(com.ebt.gateway.filter.GatewayFilter.ATTRIBUTE_IGNORE_GLOBAL_FILTER, true);
        return chain.filter(exchange);
    }

    public static class Config {
    
    
    }

    @Override
    public String name() {
    
    
        return "IgnoreGlobalFilter";
    }
}

2. yml中配置不拦截指定路径

在这里插入图片描述

3. 过滤器中配置

在这里插入图片描述

4. 设置顺序优先级,确保IgnoreGlobalFilterFactor先执行

在这里插入图片描述

七、无需认证地址的设置(针对某个url)

1. yml中配置无需认证地址

在这里插入图片描述

2. 配置组件读取地址信息

@Component
@ConfigurationProperties("spring.cloud.gateway")
public class NotAuthUrlProperties {
    
    

    private LinkedHashSet<String> shouldSkipUrls;

    public LinkedHashSet<String> getShouldSkipUrls() {
    
    
        return shouldSkipUrls;
    }

    public void setShouldSkipUrls(LinkedHashSet<String> shouldSkipUrls) {
    
    
        this.shouldSkipUrls = shouldSkipUrls;
    }
}

3. 过滤器中配置

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_50989469/article/details/127069904