Springboot-cli 软件系统定制开发开发脚手架系列
文章目录
简介
Gateway是在Spring软件系统定制开发生态系统之上构建的网关服务,基于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 Framework 5,Project Reactor和Spring Boot 2.0进行构建;
- 动态路由:能够匹配任何请求属性;
- 可以对路由指定Predicate (断言)和Filter(过滤器);
- 集成Hystrix的断路器功能;
- 集成Spring Cloud 服务发现功能;
- 易于编写的Predicate (断言)和Filter (过滤器);
- 请求限流功能;
- 支持路径重写。
1. Springcloud 整合gateway网关
- 环境
spring-cloud.version 2020.0.5spring-cloud-alibaba.version 2021.1spring-boot-dependencies.version 2.5.3
- 1
- 2
- 3
pom.xml
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
- 1
- 2
- 3
- 4
2. yml方式配置转发逻辑
- 完整配置
server: port: 20000spring: 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
routes
中为数组格式,可配置多个转发逻辑id
可自定义,不重复即可uri
配置服务地址 如lb://
+服务名称,我这里以server1
、server2
为例子,也可配置完整地址:uri: http://127.0.0.1:9999
predicates
拦截的路由filters
转发时去除前缀数量,当StripPrefix=1时:原:/server1/a/b/c 转发后为 /a/b/c
3. 编写两个服务测试效果
server-1
server: port: 20001# NaCosspring: 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}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 编写接口服务
@RestController@Slf4j@RequestMapping("/server1")public class IndexController { @GetMapping("/get") public String get() { return "我是服务1"; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
-
服务2和服务1 创建流程基本一样,这里就不上代码了
-
最后项目结构如下
-
启动网关和两个测试服务
-
浏览器输入
http://localhost:20000/server1/get
-
浏览器输入
http://localhost:20000/server2/get
-
可以发现
20000
是我们网关的端口,我们通过网关的转发成功的访问了服务1和服务2
4. 统一拦截授权
- 配置
GatewayFilter
/** * 网关拦截 * * @author ding */@Component@Slf4jpublic 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; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 当我们再次访问
http://localhost:20000/server1/get
- 观察网关服务的控制台打印可以发现,我们的拦截器已经生效了
- 具体的拦截逻辑可根据自己的业务自行实现,完整的网关授权+OAuth2实现单点登录可参考文末的项目地址,有完整源码参考。
6. 分享
本项目已收录
- Springboot、SpringCloud各种常用框架使用案例,完善的文档,致力于让开发者快速搭建基础环境并让应用跑起来,并提供丰富的使用示例供使用者参考,快速上手。