在某些情况下,部分接口需要权限分级。若是在每个微服务模块都配置一套权限框架的话,代价实在太大。所以,我们需要一个中心,来统一处理这样的请求控制。这就需要网关的作用:
网关的作用不仅只是身份认证和权限控制,还有以下作用
网关作为一个模块,也要注册到nacos注册中心里面,所以需要在父工程创建一个模块叫Gateway,测试其启动无误,并且成功注册到nacos中心。
1.启动类
package org.white;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class,args);
}
}
2.applicaiton.yml
server:
port: 6532
spring:
application:
name: Gateway
cloud:
nacos:
server-addr: http://127.0.0.1:8848
3.依赖
//这里千万别导成web了,会报错的
org.springframework.boot
spring-boot-starter-webflux
com.alibaba.cloud
spring-cloud-alibaba-nacos-discovery
2.2.0.RELEASE
启动成功后即可进入下一步
org.springframework.cloud
spring-cloud-starter-gateway
server:
port: 6532
spring:
application:
name: Gateway
cloud:
nacos:
server-addr: http://127.0.0.1
gateway:
routes:
- id: ServiceB //路由ID,随便起,不重名即可
uri: lb://ServiceB //地址,lb://表示负载均衡
predicates: //路由断言
- Path=/serviceB/** //断言规则,匹配/serviceB开头的所有URI,由断言工厂处理
- id: ServiceA
uri: lb://ServiceA
predicates:
- Path=/serviceA/**
重启后访问网关的地址就可以进入相应的服务了。
上面的路由断言我们仅仅只是使用了字符串便可以让Gateway识别到我们采用的是哪一种匹配规则。其实都是依托于PathRoutePredicateFactory这个类来处理的。
例如允许某个时间点后才可以访问:
gateway:
routes:
- id: ServiceB //路由ID,随便起,不重名即可
uri: lb://ServiceB //地址,lb://表示负载均衡
predicates: //路由断言
- Path=/serviceB/** //断言规则,匹配/serviceB开头的所有URI,由断言工厂处理
- After=2025-05-28+08:00[Asia/Shanghai] //断言规则,2025年5月28日后可以进入
断言工厂还有好十多种种规则:
详情也可以进入Spring官网查看:
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
过滤器可以让我们在处理发送和接受微服务请求时做出调整:
然而,Spring官方给出的过滤器高达30多种,具体可以前往Spring官网查看:
Gateway过滤器:
Spring Cloud Gateway
这里对AddRequestParameter这个过滤器进行一个测试:
gateway:
routes:
- id: ServiceB
uri: lb://ServiceB
predicates:
- Path=/serviceB/**
- id: ServiceA
uri: lb://ServiceA
predicates:
- Path=/serviceA/**
filters:
- AddRequestParameter=pm, 666 //","前面的是参数名,后面是值
@GetMapping("test")
public String ServiceATest(@RequestParam String pm){
String result = serviceB.serviceB(pm);
return "ServiceA Working and " + result;
}
想要给所有路由都添加过滤器的话,可以使用default-filter:
gateway:
routes:
- id: ServiceB
uri: lb://ServiceB
predicates:
- Path=/serviceB/**
- id: ServiceA
uri: lb://ServiceA
predicates:
- Path=/serviceA/**
filters:
- AddRequestParameter=pm, 666 //只对ServiceA生效
default-filters: //对所有路由生效
- AddRequestParameter=pm, 666
这个全局过滤器,从名字听起来,和上面的default-filters有点功能重复了的意思。其实这个全局过滤器叫它自定义过滤器更合适。上面我们添加的过滤器毕竟是Spring定义好了给我们的,但是如果我们想要实现更复杂的功能的话必须要手动定义过滤器。
public interface GlobalFilter {
Mono filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
exchange代表上文,chain可以放行
比如,我们想获取请求参数Auth的值是否为admin,如果是则放行:
@Component
@Order(-1)
public class AuthFilter implements GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
MultiValueMap queryParams = request.getQueryParams();
String auth = queryParams.getFirst("auth");
if ("auth".equals(auth)) {
return chain.filter(exchange);
}
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
exchange.getResponse().setComplete();
return chain.filter(exchange);
}
}
Gateway也自带了跨域配置,我们在网关配置跨域配置后,在微服务上就不用单独配置跨域了:
gateway:
routes:
- id: ServiceB
uri: lb://ServiceB
predicates:
- Path=/serviceB/**
- id: ServiceA
uri: lb://ServiceA
predicates:
- Path=/serviceA/**
filters:
- AddRequestParameter=pm, 666
globalcors:
add-to-simple-url-handler-mapping: true //允许Options
cors-configurations: //跨域配置
'[/**]':
allowedOrigins:
- "http://127.0.0.1:8080" //允许跨域的地址
allowedMethods: //允许跨域的请求
- GET
- POST
- DELETE
- PUT
- OPTIONS
allowCredentials: true //允许携带Cookie
maxAge: 36000 //允许跨域的有效期
以上就是gateway的全部内容