ZuulFilter基础

Zuul作为整个微服务架构的网关实现,是整个后台系统的入口,因此,经常会有对所有经过网关的请求进行操作的场景。这里,我们可以继承ZuulFilter类来实现自定义的过滤器。

Zuul定义的四种Filter的类型:

PRE:在请求被路由之前调用,可以使用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试Log等。
ROUTE:将请求路由到对应的微服务,用于构建发送给微服务的请求。
POST:在请求被路由到对应的微服务以后执行,可用来为Response添加HTTP Header、将微服务的Response发送给客户端等。
ERROR:在其他阶段发生错误时执行该过滤器。

从下图中可以明确了解Zuul中各种Filter执行的顺序:

Zuul中各种Filter执行的顺序

具体实现

LoginFilter.java:

package com.example.filters;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;

/**
 * Created by Skye on 2018/1/11.
 */
public class LoginFilter extends ZuulFilter {

    /**
     * 指定该Filter的类型
     * ERROR_TYPE = "error";
     * POST_TYPE = "post";
     * PRE_TYPE = "pre";
     * ROUTE_TYPE = "route";
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 指定该Filter执行的顺序(Filter从小到大执行)
     * DEBUG_FILTER_ORDER = 1;
     * FORM_BODY_WRAPPER_FILTER_ORDER = -1;
     * PRE_DECORATION_FILTER_ORDER = 5;
     * RIBBON_ROUTING_FILTER_ORDER = 10;
     * SEND_ERROR_FILTER_ORDER = 0;
     * SEND_FORWARD_FILTER_ORDER = 500;
     * SEND_RESPONSE_FILTER_ORDER = 1000;
     * SIMPLE_HOST_ROUTING_FILTER_ORDER = 100;
     * SERVLET_30_WRAPPER_FILTER_ORDER = -2;
     * SERVLET_DETECTION_FILTER_ORDER = -3;
     */
    @Override
    public int filterOrder() {
        return PRE_DECORATION_FILTER_ORDER - 1;
    }

    /**
     * 指定需要执行该Filter的规则
     * 返回true则执行run()
     * 返回false则不执行run()
     */
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String requestUrl = request.getRequestURL().toString();

        // 请求URL内不包含login或join则需要经过该过滤器,即执行run()
        return !requestUrl.contains("login") && !requestUrl.contains("join");
    }

    /**
     * 该Filter具体的执行活动
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        HttpSession httpSession = request.getSession();

        // 若session中不包含userId,则这次请求视为未登录请求,不给予路由,而提示“请登录”
        if (httpSession.getAttribute("userId") == null) {
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(200);
            // 为使得中文字符不乱码
            ctx.getResponse().setCharacterEncoding("UTF-8");
            ctx.setResponseBody("请登录");
        }
        return null;
    }
}

SpringcloudZuulApplication.java中需要包含以下代码即可使该Filter生效。

@Bean
public LoginFilter loginFilter() {
    return new LoginFilter();
}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐