# 154. 商品详情页动态渲染系统:Spring Cloud 之 Zuul 网关路由
本章讲解的就是官网教程 (opens new window)中的入门部分。
常规的 spring cloud 的微服务架构下,前端请求先通过 nginx 走到 zuul 网关服务, zuul 负责路由转发、请求过滤等网关接入层的功能,默认和 ribbon 整合实现了负载均衡
比如说你有 20 个服务暴露出去,你的调用方如果要跟 20 个服务打交道,是不是很麻烦? 所以比较好的一个方式,就是开发一个通用的 zuul 路由转发的服务,根据请求 api 模式,动态将请求路由转发到对应的服务
你的前端,主要考虑跟一个服务打交道就可以了
# 整合 zuul
创建一个新项目 zuul-server/build.gradle
plugins {
id 'org.springframework.boot' version '2.1.6.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
ext {
set('springCloudVersion', "Greenwich.SR2")
}
dependencies {
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-zuul' // 引入 zuul 依赖
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
使用注解开启
@EnableZuulProxy
1
配置路由的两个服务,application.yml
server:
port: 9010
spring:
application:
name: zuul-server
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
zuul:
routes:
greeting-service:
path: /greeting-service/**
serviceId: greeting-service
eshop-eurela-client:
path: /eshop-eurela-client/**
serviceId: eshop-eurela-client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
测试是否转发成功:
- 现在访问地址:http://localhost:9010/greeting-service/ 之前要访问:http://localhost:9001
- 现在访问地址:http://localhost:9010/eshop-eurela-client/ 之前要访问:http://localhost:9000
可以看到可以被正常转发
# 请求过滤
@Component
public class MyZuulFilter extends ZuulFilter {
private static Logger logger = LoggerFactory.getLogger(MyZuulFilter.class);
// 过滤器类型 pre,routing,post,error
@Override
public String filterType() {
return "pre";
}
// 顺序
@Override
public int filterOrder() {
return 0;
}
// 根据逻辑判断是否要过滤
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
logger.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
Object userId = request.getParameter("userId");
// 不携带 userId 这个参数就表示为未登陆
if (userId == null) {
logger.warn("userId is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
try {
ctx.getResponse().getWriter().write("userId is empty");
} catch (Exception e) {
}
return null;
}
logger.info("ok");
return null;
}
}
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
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
- 再次访问地址:http://localhost:9010/eshop-eurela-client/ ,会发现返回了 401 的错误:userId is empty
- 只能加上 userId 访问:http://localhost:9010/eshop-eurela-client/?userId=12