Zuul【自定义Filter】

我是研究僧i 提交于 2019-12-02 11:27:14

实际业务中,如果要自定义filter过滤器,只需集成ZuulFIlter类即可,该类是个抽象类,它实现了IZuulFIlter接口,我们需要实现几个方法,如下示例:

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

import javax.servlet.http.HttpServletRequest;

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

public class ThirdPreFilter extends ZuulFilter {

    /**
     * 设置filter的类型,支持4种类型
     * {@link org.springframework.cloud.netflix.zuul.filters.support.FilterConstants}
     * <pre>
     *     ERROR_TYPE = "error";//这种过滤器是在整个生命周期内,如果发生异常,就执行该filter,可以做全局异常处理。
     *     POST_TYPE = "post";//这种过滤器是在端点请求完毕,返回结果或者发生异常后执行的filter。如果需要对返回的结果进行再次处理,可以在这种过滤中处理逻辑。
     *     PRE_TYPE = "pre"; //在zuul网关按照规则路由到下级服务之前执行,如果需要对请求进行预处理,可以使用这种类型的过滤器。如:认证鉴权,限流等。
     *     ROUTE_TYPE = "route";//这种过滤器是zuul路由动作的执行者,是Apache HttpClient或Ribbon构建和发送原始HTTP请求的地方,现在也支持OKHTTP。
     * </pre>
     *
     * @return
     */
    @Override
    public String filterType() {
        return PRE_TYPE;
    }

    /**
     * 设置filter的执行顺序,数字越小,优先级越高,反之越低
     *
     * @return
     */
    @Override
    public int filterOrder() {
        return 3;
    }

    /**
     * 是否执行该过滤器,可以作为一个开关,如果一直都被执行,直接返回true即可
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        //从上下文获取logic-is-success值,用于判断此Filter是否执行
        return (boolean) ctx.get("logic-is-success");
    }

    /**
     * 该自定义filter的业务逻辑
     *
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("这是ThirdPreFilter!");
        //从RequestContext获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //从上下文获取HttpServletRequest
        HttpServletRequest request = ctx.getRequest();
        //从request尝试获取b参数值
        String b = request.getParameter("b");
        //如果b参数值为空则进入此逻辑
        if (null == b) {
            //对该请求禁止路由,也就是禁止访问下游服务
            ctx.setSendZuulResponse(false);
            //设定responseBody供PostFilter使用
            ctx.setResponseBody("{\"status\":500,\"message\":\"b参数为空!\"}");
            //logic-is-success保存于上下文,作为同类型下游Filter的执行开关,假定后续还有自定义Filter当设置此值
            ctx.set("logic-is-success", false);
            //到这里此Filter逻辑结束
            return null;
        }
        //设置避免报空指针异常
        ctx.set("logic-is-success", true);
        return null;
    }
}
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

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

public class PostFilter extends ZuulFilter {
    
    @Override
    public String filterType() {
        return POST_TYPE;
    }
    
    @Override
    public int filterOrder() {
        return 0;
    }

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

    @Override
    public Object run() throws ZuulException {
        System.out.println("这是PostFilter!");
        //从RequestContext获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //处理返回中文乱码
        ctx.getResponse().setCharacterEncoding("UTF-8");
        //获取上下文中保存的responseBody
        String responseBody = ctx.getResponseBody();
        //如果responseBody不为空,则说明流程有异常发生
        if (null != responseBody) {
            //设定返回状态码
            ctx.setResponseStatusCode(500);
            //替换响应报文
            ctx.setResponseBody(responseBody);
        }
        return null;
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!