在 Zuul 中使用过滤器

一.

今天说下Zuul 如何实现一个自定义的过滤器。实现过滤器很简单,只需要继承 ZuulFilter 类,并实现 ZuulFilter 中的抽象方法。
项目用eureka-zuul-client,参考文章

需要实现的抽象方法有:

  1. filterType(拦截器的类型):pre,routing,post,error
  2. filterOrder(执行顺序):规定了过滤器的执行顺序,Order的值越小,越先执行。
  3. shouldFilter:表示该过滤器是否过滤逻辑,为true则执行run(),为false,则不执行。
  4. run: 过滤器实际上执行的内容(即具体的过滤逻辑)

过滤器一些简单概念:

  1. PRE过滤器: 它是在请求路由到具体的服务之前执行的,可以做安全验证,例如:身份验证、参数验证等。
  2. ROUTING过滤器: 将请求转发到具体的微服务实例进行逻辑处理。在默认情况下,它使用Http Client 进行网络请求。
  3. POST过滤器: 它是在请求已被路由到微服务后执行的。一般情况下,用作收集统计信息、指标,以及将相应传输回客户端。
  4. ERROR 过滤器:: 它是在其他过滤器发生错误时执行。

二. 写一个 检查请求的参数中是否传了token这个参数,如果没有传,则直接返回响应,状态码为401

代码如下:

package com.example.eurekazuulclient.filter;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 自定义 Zuul 的过滤器
 * 写一个 检查请求的参数中是否传了token这个参数,如果没有传,则直接返回响应,状态码为401
 */
@Component
public class MyFilter extends ZuulFilter {

    private static Logger logger = LoggerFactory.getLogger(MyFilter.class);

    /**
     * filterType(拦截器的类型):pre,routing,post,error
     * filterOrder(执行顺序):规定了过滤器的执行顺序,Order的值越小,越先执行。
     * shouldFilter:表示该过滤器是否过滤逻辑,为true则执行run(),为false,则不执行。
     * run: 过滤器实际上执行的内容(即具体的过滤逻辑)
     */


    /**
     * PRE过滤器: 它是在请求路由到具体的服务之前执行的,可以做安全验证,例如:身份验证、参数验证等。
     * ROUTING过滤器: 将请求转发到具体的微服务实例进行逻辑处理。在默认情况下,它使用Http Client 进行网络请求。
     * POST过滤器: 它是在请求已被路由到微服务后执行的。一般情况下,用作收集统计信息、指标,以及将相应传输回客户端。
     * ERROR 过滤器:: 它是在其他过滤器发生错误时执行。
     */


    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

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


    /**
     * RequestContext是ConcurrentMap的一个子类,这个类可以拿到HttpServletRequest与HttpServletResponse,同时这个类当中的数据可以被多个zuulFilter共享,其中有几个方法值得我们注意以下:
     * getCurrentContext() 获取ThreadLocal中的RequestContext对象
     * setSendZuulResponse() 如果设置为false那么将终止对原始地址的路由
     * setResponseStatusCode() 设置http的状态响应码
     * addZuulResponseHeader() 设置响应头,通过这个方法我们能解决响应时中文乱码问题
     * setResponseBody() 设置响应体
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        RequestContext requestContext = RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        Object accessToken = request.getParameter("token");
        if (accessToken == null) {
            logger.info("token is empty!");
            requestContext.setSendZuulResponse(false);
            requestContext.setResponseStatusCode(401);
            //Gson gson = new GsonBuilder().create();
            requestContext.addZuulResponseHeader("content-type", "application/json;charset=utf-8");
            try {
                //requestContext.setResponseBody(gson.toJson(new ResponseEntity("token is empty!", HttpStatus.UNAUTHORIZED)));
                //requestContext.setResponseBody("token is empty!");
                requestContext.getResponse().getWriter().write("token is empty!");
            } catch (Exception e) {
                return null;
            }
        }
        logger.info("ok");
        return null;
    }
}

启动 eureka-serve,eureka-zuul-client,eureka-client (8762,8763两个端口) 服务,访问地址: http://localhost:8768/v1/hiApi/HiController/hi/java
在这里插入图片描述
从上图可以看到请求被拦截了。

接着我们带 token 去请求。http://localhost:8768/v1/hiApi/HiController/hi/java?token=1
在这里插入图片描述
到此,Zuul 中使用过滤器 学习结束

发布了33 篇原创文章 · 获赞 42 · 访问量 3153

猜你喜欢

转载自blog.csdn.net/weixin_40991408/article/details/103967719