Spring Cloud 应用篇 之 Spring Cloud Zuul(二)过滤功能

在上一篇 Spring Cloud 应用篇 之 Spring Cloud Zuul(一)路由功能 中,讲解了 Zuul 的路由功能,这一篇讲解 Zuul 的过滤功能。

(一)简介

Zuul 允许开发者在 API 网关上通过定义过滤器来实现对请求的拦截与过滤,实现的方法非常简单,我们只需继承 ZuulFilter 抽象类并实现它定义的 4 个 抽象函数就可以完成对请求的拦截和过滤了。Zuul 定义了下面四种过滤器

  • 前置(Pre)
  • 路由(Route)
  • 后置(Post)
  • 错误(Error)

(二)实现前置(Pre)过滤器

2.1 创建过滤器

这里我们仅是做案例测试,所以仅在请求被路由之前检查 HttpServletRequest 中是否有 token 参数,若有就进行路由,若没有就拒绝访问,返回 401 Unauthorized 错误。在 spring-cloud-gateway 模块中创建 PreFilter 类并继承 ZuulFilter,具体实现代码如下:

@Component
public class PreFilter extends ZuulFilter {

    private static Logger log = LoggerFactory.getLogger(PreFilter.class);

    @Override
    public String filterType() {
        return PRE_TYPE;    //过滤器类型 : pre
    }

    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER - 5;   //过滤器执行顺序,数字越小,优先级越高,越靠前,这里设置为 0
    }

    @Override
    public boolean shouldFilter() {
        return true;    //返回 true,拦截所有 URL
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();

        log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());

        String token = request.getParameter("token");
        if (StringUtils.isEmpty(token)) {
            log.warn("token is empty");
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
            return null;
        }
        log.info("token is ok");
        return null;
    }
}

在上面实现的过滤器代码中,我们通过继承 ZuulFilter 抽象类并重写下面 4 个方法来实现自定义的过滤器。这 4 个方法分别定义了如下内容。

  • filterType:过滤器的类型,它决定过滤器在请求的哪个生命周期中执行。这里定义为 pre,代表会在请求被路由之前执行。
  • filterOrder:过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时,需要根据该方法返回值来依次执行。
  • shouldFilter:判断该过滤器是否需要被执行。这里直接返回了 true,因此该过滤器对所有请求都会生效。实际运用中可以利用该函数来指定过滤器的有效范围。
  • run:过滤器的具体逻辑。这里通过 requestContext.setSendZuulResponse(false) 令 Zuul 过滤该请求,不对其进行路由,然后通过 requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()) 设置了其返回的错误码,当然也可以对返回的结果进行优化,比如,通过 requestContext.setResponseBody(body) 对返回的 body 内容进行编辑等。

2.2 验证过滤器

访问 http://localhost:9001/demoService/port,这个请求的 URL 并没有 token 参数,所以请求被拦截,结果如下

 Spring Cloud 应用篇 之 Spring Cloud Zuul(二)过滤功能_第1张图片

从后台日志也可以看出,请求被拦截

Spring Cloud 应用篇 之 Spring Cloud Zuul(二)过滤功能_第2张图片


下面访问 http://localhost:9001/demoService/port?token=123,这个 URL 有 token 参数,所以顺利被 Zuul 路由,结果如下

Spring Cloud 应用篇 之 Spring Cloud Zuul(二)过滤功能_第3张图片

从后台日志中也可以看出,请求没有被拦截



(三)简单实现后置(Post)过滤器

3.1 创建过滤器

这里简单的对请求的 response 设置一个 header,代码如下,实现逻辑和 Pre 过滤器类似

@Component
public class PostFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return POST_TYPE;
    }

    @Override
    public int filterOrder() {
        return SEND_RESPONSE_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletResponse response = requestContext.getResponse();
        response.setHeader("geny", "shmily");
        return null;
    }
}

3.2 验证过滤器

访问 http://localhost:9001/demoService/port?token=123,可以看到,对 response 设置的 header 已经成功返回。

Spring Cloud 应用篇 之 Spring Cloud Zuul(二)过滤功能_第4张图片


源码下载:https://github.com/shmilyah/spring-cloud-componets


你可能感兴趣的:(Spring,Cloud,应用篇,Spring,Cloud,Finchley)