通常,我们需要在请求到达之间处理一些相同的操作,比如验证是否用户登陆,或者是判断有没有必需要的信息,所以就有了zuul中的自定义filter
实现一个zuul的自定义filter非常简单,分成三步:
1.创建一个过滤器类并继承ZuulFilter,根据自己的需求来写业务流程,如果还不会zuul的可以参考我的上一篇博客:https://blog.csdn.net/qq_43222167/article/details/105727877
这里我新建了两个过滤器,简单的说明一下它们的流程
第一步:
对用户名的判断类
package com.jbit.myfilter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
public class PreNameFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre"; //前置过滤器
}
@Override
public int filterOrder() {
return 0; //优先级为0,数字越大,优先级越低
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
System.out.println("PreNameFilter");
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println(request.getRequestURL().toString());
String userName = request.getParameter("userName");//获取请求参数
if (null != userName && userName.equals("kk")) {//如果请求的参数不为空,且值为自己所设定的则通过,我这里设定的是kk
ctx.setSendZuulResponse(true); //对该请求进行路由
ctx.setResponseStatusCode(200);//设置状态码
ctx.set("flag", true); //设置,让下一个Filter看到上一个Filter的状态
return null;
} else {
System.out.println("用户名为空或者是不是kk");
ctx.setSendZuulResponse(false);//过滤该请求,不对其进行路由
ctx.setResponseStatusCode(401);//返回错误码
ctx.set("flag", false); //让下一个Filter看到上一个Filter的状态
return null;
}
}
}
下面是对各个方法的说明:
filterType(),返回值有四种:
error:处理请求时发生错误时被调用
post:在route和error过滤器之后被调用
pre:可以在请求被路由之前调用
route:在路由请求时候被调用
filterOrder():设置请求的优先级,基于filterType()的同类
shouldFilter():是否执行该过滤器,此处为true,说明需要过滤
run():过滤器的逻辑。如果shouldFilter()为false则根本不会进来
对密码的判断:
package com.jbit.myfilter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import javax.servlet.http.HttpServletRequest;
public class PrePasswordFilter extends ZuulFilter {
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 1; //设置优先级为1
}
@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
//如果前一个过滤器的结果为true,则说明上一个过滤器成功了,需要进行当前的过滤
//如果前一个过滤器的结果为false,则说明上一个过滤器没有成功,则无需进行下面的过滤动作了,直接跳过后面的所有过滤器并返回结果
return (boolean) ctx.get("flag");
}
@Override
public Object run() {
System.out.println("PrePasswordFilter");
RequestContext ctx=RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
System.out.println(request.getRequestURL().toString());
String password=request.getParameter("password");
if(null!=password && password.equals("kkc")){
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
ctx.set("flag",true);
return null;
}else{
System.out.println("密码为空或者不是kkc");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
ctx.set("flag",false);
return null;
}
}
}
第二步:在启动类中增加@Bean
@Bean
public PreNameFilter zuulPreNameFilter(){
return new PreNameFilter();
}
@Bean
public PrePasswordFilter zuulPrePasswordFilter(){
return new PrePasswordFilter();
}
增加两个返回你自定义Filter对象的方法
第三步:访问测试
1.我先不输入正确的用户名或不输入用户名
进入了对用户名判断的过滤器,但由于不是正确的用户名,所以到对用户密码判断过滤器的时候shouldFilter()中获取标识的时候为false,所以不进入用户密码过滤器的run()方法中
2.正确的用户名,密码错误
进入了用户密码过滤器的run方法中,但由于密码错误所以不进入自己相应的请求
3.账号密码都正确
两个过滤器都通过并且访问到了相应请求中的数据
对过滤器的流程我是这样理解的:没有直接的方法来访问对方。它们可以使用RequestContext来共享状态内容,我的理解是一次请求经过多个过滤器然后通过特定的对象来处理信息