Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor等技术。
SpringCloud Gateway是Spring Cloud的一个全新项目,基于Spring 5.0+Spring Boot 2.0和Project Reactor等技术开发的网关,它旨在为微服务架构提供—种简单有效的统一的API路由管理方式。
SpringCloud Gateway作为Spring Cloud 生态系统中的网关,目标是替代Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 1.x非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。
SpringCloud Gateway具有如下特性
spring-cloud.version 2020.0.5
spring-cloud-alibaba.version 2021.1
spring-boot-dependencies.version 2.5.3
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
server:
port: 20000
spring:
application:
name: gateway
# NaCos
cloud:
service-registry:
auto-registration:
# 是否注册到注册中心
enabled: true
nacos:
discovery:
server-addr: 192.168.41.128:8848
namespace: 4c016e5c-cacb-44d5-955d-22754ede9fce
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yaml
prefix: ${spring.application.name}
# 网关
gateway:
default-filters:
- DedupeResponseHeader=Vary Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_UNIQUE
- DedupeResponseHeader=Access-Control-Allow-Origin, RETAIN_FIRST
discovery:
locator:
enabled: true
lowerCaseServiceId: true
routes:
# 服务1
- id: server-1
# 服务地址
uri: lb://server-1
# 拦截的路由
predicates:
- Path=/server1/**
# 转发时去除前缀数量,当为1时:原:/server1/a/b/c 转发后为 /a/b/c
filters:
- StripPrefix=0
# 服务2
- id: server-2
uri: lb://server-2
predicates:
- Path=/server2/**
filters:
- StripPrefix=0
routes
中为数组格式,可配置多个转发逻辑id
可自定义,不重复即可uri
配置服务地址 如 lb://
+服务名称,我这里以server1
、server2
为例子,也可配置完整地址:uri: http://127.0.0.1:9999
predicates
拦截的路由filters
转发时去除前缀数量,当StripPrefix=1时:原:/server1/a/b/c 转发后为 /a/b/cserver-1
server:
port: 20001
# NaCos
spring:
application:
name: server-1
# NaCos
cloud:
service-registry:
auto-registration:
# 是否注册到注册中心
enabled: true
nacos:
discovery:
server-addr: 192.168.0.251:8848
# namespace: 4c016e5c-cacb-44d5-955d-22754ede9fce
namespace: be88b2b8-987c-4801-a5f1-05b867e6370e
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${spring.cloud.nacos.discovery.namespace}
file-extension: yaml
prefix: ${spring.application.name}
@RestController
@Slf4j
@RequestMapping("/server1")
public class IndexController {
@GetMapping("/get")
public String get() {
return "我是服务1";
}
}
服务2和服务1 创建流程基本一样,这里就不上代码了
启动网关和两个测试服务
可以发现20000
是我们网关的端口,我们通过网关的转发成功的访问了服务1和服务2
GatewayFilter
/**
* 网关拦截
*
* @author ding
*/
@Component
@Slf4j
public class GatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
String url = request.getURI().getPath();
log.info("接收到请求:{}", url);
// 跨域放行
if (request.getMethod() == HttpMethod.OPTIONS) {
response.setStatusCode(HttpStatus.OK);
return Mono.empty();
}
// 授权
if (!this.auth(exchange, chain)) {
return this.responseBody(exchange, 406, "请先登录");
}
return chain.filter(exchange);
}
/**
* 认证
*/
private boolean auth(ServerWebExchange exchange, GatewayFilterChain chain) {
// 逻辑自行实现
String token = this.getToken(exchange.getRequest());
log.info("token:{}", token);
return true;
}
/**
* 获取token
*/
public String getToken(ServerHttpRequest request) {
String token = request.getHeaders().getFirst("token");
if (StringUtils.isBlank(token)) {
return request.getQueryParams().getFirst("token");
}
return token;
}
/**
* 设置响应体
**/
public Mono<Void> responseBody(ServerWebExchange exchange, Integer code, String msg) {
String message = JSON.toJSONString(new ResponseResult<>(code, msg));
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
return this.responseHeader(exchange).getResponse()
.writeWith(Flux.just(exchange.getResponse().bufferFactory().wrap(bytes)));
}
/**
* 设置响应体的请求头
*/
public ServerWebExchange responseHeader(ServerWebExchange exchange) {
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, "application/json");
return exchange.mutate().response(response).build();
}
@Override
public int getOrder() {
return -100;
}
}
http://localhost:20000/server1/get
本项目已收录