9.天气预报系统-API网关 中已经对API网关进行了详细的介绍。基础的概念就不再赘述了。下面着重看一下zuul中如何实现过滤器。

基本使用

第一步:创建一个springboot工程,引入依赖:

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
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<!--Eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!--zuul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
</dependencies>

第二步:在启动函数上增加注解:

1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class SpringCloudEurekaZuulApplication {

public static void main(String[] args) {
SpringApplication.run(SpringCloudEurekaZuulApplication.class, args);
}
}

第三步:配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:
application:
name: api-gateway
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
zuul:
routes:
service-hi:
path: /service-hi/**/
serviceId: service-hi
server:
port: 8084

主要就是配置路由规则,以service-hi为前缀的都去serivce-hi为名字的服务下找对应的映射。

这样,就完成了基本的整合。启动其他的项目:spring-cloud-eureka-server-1,spring-cloud-eureka-server-2,spring-cloud-eureka-client-1,spring-cloud-eureka-client-1.

在我的spring-cloud-eureka-client-1有一个路径叫localhost:8080/test返回一个字符串。那么此时用网关来访问的话应该是:localhost:8084/service-hi/test.

过滤器

新建一个类,假设我们要检验token,如果token为空,就返回未授权。

TokenFilter:

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
public class TokenFilter extends ZuulFilter {

//pre 在路由表寻找路由时生效
//routing 找到路由开始进行请求转发时生效
//error 出错时生效
//post routing或者error之后最后阶段生效
@Override
public String filterType() {
return "pre";
}

//越小,优先级越高
@Override
public int filterOrder() {
return 0;
}

//true表示过滤器生效
@Override
public boolean shouldFilter() {
return true;
}

@Override
public Object run() throws ZuulException {
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();
String token = request.getParameter("token");
if(token == null){
context.setSendZuulResponse(false);
context.setResponseStatusCode(401);
context.setResponseBody("unsutherized");
return null;
}
return null;
}
}

要将其注册到spring:

1
2
3
4
@Bean
public TokenFilter tokenFilter(){
return new TokenFilter();
}

再次访问localhost:8084/service-hi/test时,显示unsutherized,当访问localhost:8084/service-hi/test?token=123时访问通过。

如果在run()中出现异常,但是这个异常不能抛出来显示在页面上。那么如何在页面上如何显示呢?在catch的代码中这样写:

1
2
3
context.set(error.status_code,401);
context.set("error.exception",e);
context.set("error.message","提示信息");