在Vertx Web的体系下,如何做一个Action级别的拦截器?

列车
  • 73

我希望能进行参数校验,权限校验,登录校验等校验检查和认证操作,但是我希望的是当一个请求成功匹配一个路由后(Route),在真正调用路由处理的方法前,也就是Handler<RoutingContext> 之前,在调用调用一个返回参数为Void方法,我想在这个方法内编写校验检查认证的代码,以此作为拦截器。

我的最终目的是需要一个Action级别的拦截器,但是Vertx没有提供这个组件,那么我就得自定义拦截组件,还是在基于Vert.x Web路由配置基础上实现。那么我设想至少流程应该是这样的,

VertxHttp服务端收到了一个请求——>创建RoutingContext对象——>将RoutingContext对象与使用者配置的Route进行匹配——>请求匹配Route成功——>调用自定义拦截组件——>拦截校验全部通过——>调用最终的Action本身的Handler<RoutingContext>方法。

按照这个流程来提问,那么我要问的是,“调用自定义拦截组件“,这个步骤是怎么接上“匹配请求Route成功”的,既然请求匹配Route成功了,后面又调用了拦截器组件。那么至少肯定得有个匹配Route成功的调用个接口来对接吧。这样传递一个接口实现类,在接口的实现类上,就可以实现自定义拦截功能。

目前我知道的方法是,弄一个类实现Route的handler方法的handler<RoutingContext> 接口,将Handler接口的handler方法实现,作为拦截方法,用另一个Handler<RoutingContext>类型的函数字段代替Handler作为action处理,在handler方法内就可以实现拦截了,写一个if逻辑语句实现最简单的拦截效果。但这个实现的方式如果要实现全局拦截(拦截所有未匹配排除项的Route)太绕了。能不能直接在Router上扩展?

回复
阅读 2.3k
2 个回答
okou
  • 2
新手上路,请多包涵
String path = "/filter.path";
router.route(path).handle(rc -> {
    if(xxx) {
        rc.next();
    } else {
        rc.fail(403);
    }
});

router.route(path).handle(rc -> {
    //do action
});
列车
  • 73

@okou

Action拦截器的特点是,只要请求匹配到了Action,就拦截,没有匹配就不拦截请求。

以下我编写的Action级别的拦截器实现,基于Route的handler方法的形式参数类型接口的实现类来弄的,path和action处理方法配置也要经过该实现类来配置。

在实现类的内部实现统一拦截功能(例如静态属性),然后所有需要统一拦截的Route的handler都是使用该接口实现类作为参数

实现类源码:

public   class ActionHandler implements Handler<RoutingContext> {

    
    String path;
    
    protected  Handler<RoutingContext> actionFunc;
    
    protected ActionInfo info;
    
    
    public ActionHandler setHandler(Handler<RoutingContext> actionFunc) {
        this.actionFunc = actionFunc;
        return this;
    }
    

    public ActionHandler setInfo(ActionInfo info) {
        
        this.info = info;
        return this;
    }

    @Override
    public void handle(RoutingContext event) {
        // TODO Auto-generated method stub
        
        
        if(Vail(event)) {
            try {
                actionFunc.handle(event);
            }catch (Exception e) {
                event.response().setStatusCode(500);
                event.response().end("Server Error");
                e.printStackTrace();
                throw new RuntimeException("运行Action方法错误:"+e.getMessage());
                
            }
            
        }else {
            event.response().setStatusCode(400);
            event.response().end("parmas Error");
        }
        
    }
    
    /**
     * 顺序验证方法,不要做异步验证
     * 
     */
    public boolean Vail(RoutingContext context) {
        if(info!=null) {
                        //是否包含必要的Query参数?
            for(String name: info.queryParamsMustContain) {
                if(context.queryParams().names().contains(name)==false) {
                    return false;
                    
                }
            }
        }
        
            
            return true;
    }
}

构造一个ActionHandler对象,并将传给Route的handler方法

使用:设置两个Action,并配置统一的拦截功能

//反射配置



//例1
ActionHandler a=new ActionHandler().setHandler((context)->{

context.end();
});
a.path="/test";
router.route(a.path).handler(a);
//例2
ActionHandler a2=new ActionHandler().setHandler((context)->{

context.end("5555");
});
a2.path="/test/test2";
router.route(a2.path).handler(a2);

以上是测试使用,没有用反射。
除了基于Route的handler方法的参数实现类做拦截器,你还有什么其他的方法吗,来实现吗?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏