vlambda博客
学习文章列表

Vert.x系列04 - 你意想不到的那些路由规则

简介

前面介绍了,vert.x的基本概念,使用vert.x构建一个简单的HttpServer,为Vert.x应用添加路由器, 接下来我们继续介绍 Vert.x的路由规则.


Vert.x 的路由规则

Vert.x的路由规则主要有以下几种:
  • 通过指定的路径进行路由

  • 正则匹配的路由

  • 根据请求方法进行路由

  • 根据请求的MIME类型进行路由

  • 根据客户端可接受的 MIME 类型进行路由

注意: 以上路由方式可以混合使用.
下面演示下上面几种路由的使用方式
  
    
    
  
HttpServer httpServer = vertx.createHttpServer();

Router router = Router.router(vertx);

// 只会捕获到 /fxb/path 这个路由
router.route().path( "/fxb/path").handler(routingContext -> {
routingContext.response().end( "fxb/path");
});
// 获取以action结尾的路由
router.route().pathRegex( ".*action").handler(routingContext -> {
routingContext.response().end( ".*action");
});
// 捕获以 "/fxb/path/"开头的路由
router.route().path( "/fxb/path/*").handler(routingContext -> {
routingContext.response().end( "/fxb/path/*");
});
// 获取 正则匹配路由的中的路由参数 - 给分组命名
router.routeWithRegex( "\\/(?<id>[^\\/]+)\\/(?<name>[^\\/]+)").handler(routingContext -> {
String id = routingContext.request().getParam( "id");
String name = routingContext.request().getParam( "name");
String format = String.format( "fxb/param/路由, 获取到的参数: id=[%s],name=[%s]", id, name);
routingContext.response().end(format);
});
// 只接收POST请求
router.route(HttpMethod.POST, "/fxb/method/*").handler(routingContext -> {
routingContext.response().end( "/fxb/method/*");
});
// 基于Request的MIME类型的路由(consumes可以指定多个,也支持*/json这种格式)
router.route().consumes( "text/html/").path( "/fxb/mime/consumes/").handler(routingContext -> {
routingContext.response().end( "/fxb/mime/consumes/的text/html");
});

// 基于客户端可接受的MIME类型的路由
router.route().produces( "text/html/").path( "/fxb/mime/produces/").handler(routingContext -> {
routingContext.response().end( "/fxb/mime/produces/的text/html");
});

/// 以上的路由方式可随意结合使用
httpServer.requestHandler(router).listen( 8080);
如果你想获取路由中的参数怎么办呢?可以通过下面这种方式来获取
 
  
    
    
  
// 获取路由中的参数
router.route().path( "/fxb/param/:id/:name").handler(routingContext -> {
String id = routingContext.request().getParam( "id");
String name = routingContext.request().getParam( "name");
String format = String.format( "fxb/param/路由, 获取到的参数: id=[%s],name=[%s]", id, name);
routingContext.response().end(format);
});
// 获取 正则匹配路由的中的路由参数
router.route().pathRegex( "*.action").pathRegex( "\\/([^\\/]+)\\/([^\\/]+)").handler(routingContext -> {
String id = routingContext.request().getParam( "param0");
String name = routingContext.request().getParam( "param1");
String format = String.format( "fxb/param/路由, 获取到的参数: id=[%s],name=[%s]", id, name);
routingContext.response().end(format);
});

路由匹配顺序

默认的情况下, 路由会根据其加入到路由器的顺序进行匹配. 如下面的的例子:
  
    
    
  
Router router = Router.router(vertx);

router.route( "/some/path/").handler(routingContext -> {
routingContext.response().write( "handler1");
routingContext.next();
});
router.route( "/some/path/").handler(routingContext -> {
routingContext.response().setChunked( true).write( "handler2");
routingContext.next();
});

router.route( "/some/path/").handler(routingContext -> {
routingContext.response().end( "handler3");
});

vertx.createHttpServer().requestHandler(router).listen( 8080);
我们可以使用order属性进行排序
  
    
    
  
Router router = Router.router(vertx);

router.route( "/some/path/").order( 1).handler(routingContext -> {
routingContext.response().setChunked( true).write( "handler1");
routingContext.next();
});
router.route( "/some/path/").order( 0).handler(routingContext -> {
routingContext.response().write( "handler2");
routingContext.next();
});

router.route( "/some/path/").order( 2).handler(routingContext -> {
routingContext.response().end( "handler3");
});

vertx.createHttpServer().requestHandler(router).listen( 8080);

其他功能

启动禁用路由

这个比较简单,
router 对象有一个属性是 order, 我们可以通过该属性来设置这条路由是否生效. 如下。
  
    
    
  
router.route( "/some/path/").order( 1).handler(routingContext -> {
routingContext.response().write( "handler1");
routingContext.next();
}).disable()

重新路由

Route.handler() 这个方法中, 的 Handler<RoutingContext> 中的 RoutingContext 有一个 reroute方法.
这个方法,可以引导当前路由到指定的路由上.
  
    
    
  
router.route( "/some/path/").order( 1).handler(routingContext -> {
routingContext.response().write( "handler1");
routingContext.reroute( "/some/path2/");
});

子路由器

  
    
    
  
Router sonRouter = Router.router(vertx);
sonRouter.route( "/son").handler(routingContext -> {});

Router mainRouter = Router.router(vertx);
mainRouter.mountSubRouter( "/main",sonRouter).route( "/main");
这样就通过 mountSubRouter 完成了 将 sonRouter 作为了 mainRouter 的子路由器. 访问子路由器需要 /main/son/

小结

  • 路由规则

    • 通过指定的路径进行路由

    • 正则匹配的路由

    • 根据请求方法进行路由

    • 根据请求的MIME类型进行路由

    • 根据客户端可接受的 MIME 类型进行路由

  • 获取路由中的参数

    • 普通路由中的参数

    • 正则匹配方式中的参数

  • 路由顺序

  • 其他功能

    • 启用/禁用路由

    • 重新路由

    • 子路由