SpringCloud进击 | 六浅出:服务网关 - 过滤器(Zuul Filter)【Finchley版本】

1.前言

Zuul 本身是一系列过滤器的集成,那么他当然也就提供了自定义过滤器的功能,Zuul 提供了四种过滤器:前置过滤器,路由过滤器,错误过滤器,简单过滤器。实现起来也非常简单,只需要编写一个类去实现 Zuul 提供的接口 - ZuulFilter。

上一节:SpringCloud进击 | 五浅出:服务网关 - 路由(Zuul Router)【Finchley版本】

 

2.准备

延用第五节的项目,并分别启动以下模块:

  • 服务注册中心:wei-eureka-server,端口号:8090(无需修改,正常启动)
  • 服务提供者:wei-service-provider,端口号:8010、8011(以端口号正常启动)
  • 服务消费者:wei-consumer-ribbon,端口号:8023(以端口号正常启动)
  • 服务网关:wei-gateway-zuul,端口号:8040(本节修改对象)

确认除 wei-gateway-zuul 外,已经分别正常启动以上应用模块。服务注册中心(http://localhost:8090/)查看服务,如下,注册成功:

【Eureka Server】

首先,可以正常访问服务:http://localhost:8040/api/consumerGroup/demo/info?name=tester

Hi,tester,我是服务,我被调用了,服务名为:wei-service-provider,端口为:8011

如果不能正常访问,可以看看上一节 SpringCloud进击 | 五浅出:服务网关 - 路由(Zuul Router)【Finchley版本】

如上,准备工作完成。

 

3.进击

3.1.pom.xml依赖

文件与上一节相同,无需改造

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.wei</groupId>
    <artifactId>wei-gateway-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>wei-gateway-zuul</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

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

        <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>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>

</project>

3.2.application.yml配置文件

文件与上一节相同,无需改造

server:
  port: 8040    # 自定义程序启动端口
spring:
  application:
    name: wei-gateway-zuul    # 指定进行服务注册时该服务的名称,服务与服务之间相互调用一般都是根据这个name
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8090/eureka/    # 指定进行服务注册的地址
zuul:
  routes:    # 配置路由映射
    wei-service-provider: /providerGroup/**    # 服务名称映射。给指定的服务做映射,当前配置是将/wei-service-provider/**映射为/providerGroup/**
    consumerGroup:    # 保证唯一
      #url: http://localhost:8022/    # url绑定映射
      serviceId: wei-consumer-ribbon    # 给指定的服务做映射
      path: /consumerGroup/**    # path绑定映射。配置映射的路径,当前配置是将/wei-consumer-ribbon/**映射为/consumerGroup/**
  prefix: /api
ribbon:
  eureka:
    enabled: false    # 在eureka中禁用 ribbon 的负载均衡
wei-consumer-ribbon:
  ribbon:    # 给配置serviceId对应的服务指定ribbon负载均衡,从listOfServers配置的服务地址中分配服务,多个用半角逗号分隔
    listOfServers: http://localhost:8010/, http://localhost:8011/

3.3.Zuul过滤器

新增过滤器,通过继承 ZuulFilter 抽象类,编写自定义 Filter。

package com.wei.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

@Component
public class WeiZuulFilter extends ZuulFilter {

    /**
     * 类型包含 pre、post、route、error
     * pre:在路由代理之前执行
     * route:代理的时候执行
     * error:出现错的时候执行
     * post:在route 或者是 error 执行完成后执行
     *
     * 过滤器的类型,它决定过滤器在请求的哪个生命周期中执行
     * 这里定义为pre,表示会在请求被路由之前执行
     *
     * @return 过滤器类型
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * Zuul filter 为链式过滤器,多个filter按顺序执行,通过数字指定
     * 数字越大,优先级越低
     *
     * @return 执行顺序
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 是否启用该过滤器
     * 判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有请求都会生效
     * 实际运用中我们可以利用该函数来指定过滤器的有效范围
     *
     * @return true:启用过滤器 / false:禁用过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器的具体逻辑实现Demo
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {

        System.out.println("[ Demo For Zuul Filter ] Execute!");

        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        String token = request.getParameter("token");

        if (StringUtils.isEmpty(token)) {
            System.out.println("[ Demo For Zuul Filter ] token parameter is empty!");

            // 使用 Zuul 过滤此种场景的请求,不对其进行路由
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(401);
            requestContext.setResponseBody("token is empty!");
        } else {
            System.out.println("[ Demo For Zuul Filter ] test success!");
        }

        return null;
    }
}

3.4.启动类

文件与上一节相同,无需要改造

package com.wei;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;

/**
 * 注解@EnableZuulProxy,开启Zuul功能,自带熔断
 */
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class WeiGatewayZuulApplication {

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

 

好了,到此,Zuul Filter 过滤器就已添加完成。其实只是增加并实现了一个自定义 ZuulFilter 类。

重启这个启动类。

 

4.测试

访问:http://localhost:8040/api/consumerGroup/demo/info?name=tester

浏览器输出:

token is empty!

后台日志打印:

【Zuul Filter】

前端看一看,请求返回结果状态是401。如此,说明 Zuul 过滤器已经在正常工作。

 

那我们把 token 参数加上:token=token_test

访问:http://localhost:8040/api/consumerGroup/demo/info?name=tester&token=token_test

浏览器打印:

Hi,tester,我是服务,我被调用了,服务名为:wei-service-provider,端口为:8010

后台日志打印:

【Zuul Filter】

有木有,通过过滤器,Zuul 正确路由到了配置文件配置好的 加了前缀(/api) 映射(/consumerGroup)的 /demo/info 接口。

 

5.总结

上面的代码实现过程中,当通过继承 ZuulFilter 抽象类后,需要我们重写它的四个方法:

  • filterType():过滤器的类型。它决定过滤器在请求的哪个生命周期中执行。其类型包含 pre、post、route、error。
  1. pre:在路由代理之前执行
  2. route:代理的时候执行
  3. error:出现错的时候执行
  4. post:在route 或者是 error 执行完成后执行
  • filterOrder():过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回的值来依次执行。通过数字指定,数字越大,优先级越低。
  • shouldFilter():判断该过滤器是否需要被执行。这里我们直接返回了true,因此该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的有效范围。
  • run():过滤器的具体逻辑。这里我们只是简单实现了一下,使用 Zuul 过滤入参没有 token 场景的请求,不对其进行路由。

 

参考文档:
https://springcloud.cc/spring-cloud-netflix.html
http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#_router_and_filter_zuul


下一节,请继续关注:SpringCloud进击 | 七浅出:配置中心(Git配置与更新)【Finchley版本】

 

6.物语

SpringCloud进击 | 一浅出:服务注册与发现(Eureka)【Finchley版本】
SpringCloud进击 | 二浅出:服务消费者(Ribbon+REST)【Finchley版本】
SpringCloud进击 | 三浅出:服务消费者(Feign)【Finchley版本】
SpringCloud进击 | 四浅出:断路器与容错(Hystrix)【Finchley版本】
SpringCloud进击 | 五浅出:服务网关 - 路由(Zuul Router)【Finchley版本】
SpringCloud进击 | 六浅出:服务网关 - 过滤器(Zuul Filter)【Finchley版本】
SpringCloud进击 | 七浅出:配置中心(Git配置与更新)【Finchley版本】
SpringCloud进击 | 一深入:配置中心(服务化与高可用)【Finchley版本】
SpringCloud进击 | 二深入:配置中心(消息总线)【Finchley版本】
SpringCloud进击 | 三深入:服务链路跟踪(Spring Cloud Sleuth)【Finchley版本】
SpringCloud进击 | 四深入:服务链路跟踪(Sleuth+Zipkin+RabbitMQ整合)【Finchley版本】
SpringCloud进击 | 五深入:断路器监控(Hystrix Dashboard)【Finchley版本】
SpringCloud进击 | 六深入:断路器聚合监控(Hystrix Turbine)【Finchley版本】
SpringCloud进击 | 七深入:高可用的服务注册中心【Finchley版本】

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值