Vert.x-web的讲解和使用(英文原版)

Vert.x-Web是用于构建现代、可扩展的Web应用的一组构建块,基于Vert.x核心提供更丰富的功能,适合RESTful API、实时Web应用等。它包括路由、路径匹配、请求处理、会话管理、认证授权、静态资源服务、模板引擎等多种特性,并支持SockJS和事件总线桥接。本文档详细介绍了Vert.x-Web的各项功能和用法。
摘要由CSDN通过智能技术生成

Vert.x-Web

Vert.x-Web is a set of building blocks for building web applications with Vert.x.

Think of it as a Swiss Army Knife for buildingmodern, scalable, web apps.

Vert.x core provides a fairly low level set of functionality for handling HTTP, and for some applicationsthat will be sufficient.

VVert.x-Web builds on Vert.x core to provide a richer set of functionality for building real web applications, moreeasily.

It’s the successor to Yoke in Vert.x 2.x, and takes inspiration from projects suchas Express in the Node.js world and Sinatra in the Ruby world.

Vert.x-Web is designed to be powerful, un-opionated and fully embeddable. You just use the parts you want and nothing more.Vert.x-Web is not a container.

You can use Vert.x-Web to create classic server-side web applications, RESTful web applications, 'real-time' (server push)web applications, or any other kind of web application you can think of. Vert.x-Web doesn’t care. It’s up to you to chosethe type of app you prefer, not Vert.x-Web.

Vert.x-Web is a great fit for writing RESTful HTTP micro-services, but we don’tforce you to write apps like that.

Some of the key features of Vert.x-Web include:

  • Routing (based on method, path, etc)

  • Regular expression pattern matching for paths

  • Extraction of parameters from paths

  • Content negotiation

  • Request body handling

  • Body size limits

  • Cookie parsing and handling

  • Multipart forms

  • Multipart file uploads

  • Sub routers

  • Session support - both local (for sticky sessions) and clustered (for non sticky)

  • CORS (Cross Origin Resource Sharing) support

  • Error page handler

  • Basic Authentication

  • Redirect based authentication

  • Authorisation handlers

  • JWT based authorization

  • User/role/permission authorisation

  • Favicon handling

  • Template support for server side rendering, including support for the following template engines out of the box:

    • Handlebars

    • Jade,

    • MVEL

    • Thymeleaf

  • Response time handler

  • Static file serving, including caching logic and directory listing.

  • Request timeout support

  • SockJS support

  • Event-bus bridge

Most features in Vert.x-Web are implemented as handlers so you can always write your own. We envisage many more being writtenover time.

We’ll discuss all these features in this manual.

Using Vert.x Web

To use vert.x web, add the following dependency to the dependencies section of your build descriptor:

  • Maven (in your pom.xml):

<dependency>
  <groupId>{maven-groupId}</groupId>
  <artifactId>{maven-artifactId}</artifactId>
  <version>{maven-version}</version>
</dependency>
  • Gradle (in your build.gradle file):

compile {maven-groupId}:{maven-artifactId}:{maven-version}

Re-cap on Vert.x core HTTP servers

Vert.x-Web uses and exposes the API from Vert.x core, so it’s well worth getting familiar with the basic concepts of writingHTTP servers using Vert.x core, if you’re not already.

The Vert.x core HTTP documentation goes into a lot of detail on this.

Here’s a hello world web server written using Vert.x core. At this point there is no Vert.x-Web involved:

HttpServer server = vertx.createHttpServer();

server.requestHandler(request -> {

  // This handler gets called for each request that arrives on the server
  HttpServerResponse response = request.response();
  response.putHeader("content-type", "text/plain");

  // Write to the response and end it
  response.end("Hello World!");
});

server.listen(8080);

We create an HTTP server instance, and we set a request handler on it. The request handler will be called whenevera request arrives on the server.

When that happens we are just going to set the content type to text/plain, and writeHello World! and end theresponse.

We then tell the server to listen at port 8080 (default host is localhost).

You can run this, and point your browser at http://localhost:8080 to verify that it works as expected.

Basic Vert.x-Web concepts

Here’s the 10000 foot view:

A Router is one of the core concepts of Vert.x-Web. It’s an object which maintains zero or moreRoutes .

A router takes an HTTP request and finds the first matching route for that request, and passes the request to that route.

The route can have a handler associated with it, which then receives the request. You thendo something with therequest, and then, either end it or pass it to the next matching handler.

Here’s a simple router example:

HttpServer server = vertx.createHttpServer();

Router router = Router.router(vertx);

router.route().handler(routingContext -> {

  // This handler will be called for every request
  HttpServerResponse response = routingContext.response();
  response.putHeader("content-type", "text/plain");

  // Write to the response and end it
  response.end("Hello World from Vert.x-Web!");
});

server.requestHandler(router::accept).listen(8080);

It basically does the same thing as the Vert.x Core HTTP server hello world example from the previous section,but this time using Vert.x-Web.

We create an HTTP server as before, then we create a router. Once we’ve done that we create a simple route withno matching criteria so it will matchall requests that arrive on the server.

We then specify a handler for that route. That handler will be called for all requests that arrive on the server.

The object that gets passed into the handler is a RoutingContext - this containsthe standard Vert.xHttpServerRequest andHttpServerResponsebut also various other useful stuff that makes working with Vert.x-Web simpler.

For every request that is routed there is a unique routing context instance, and the same instance is passed toall handlers for that request.

Once we’ve set up the handler, we set the request handler of the HTTP server to pass all incoming requeststoaccept.

So, that’s the basics. Now we’ll look at things in more detail:

Handling requests and calling the next handler

When Vert.x-Web decides to route a request to a matching route, it calls the handler of the route passing in an instanceofRoutingContext.

If you don’t end the response in your handler, you should call next so anothermatching route can handle the request (if any).

You don’t have to call next before the handler has finished executing.You can do this some time later, if you want:

Route route1 = router.route("/some/path/").handler(routingContext -> {

  HttpServerResponse response = routingContext.response();
  // enable chunked responses because we will be adding data as
  // we execute over other handlers. This is only required once and
  // only if several handlers do output.
  response.setChunked(true);

  response.write("route1\n");

  // Call the next matching route after a 5 second delay
  routingContext.vertx().setTimer(5000, tid -> routingContext.next());
});

Route route2 = router.route("/some/path/").handler(routingContext -> {

  HttpServerResponse response = routingContext.response();
  response.write("route2\n");

  // Call the next matching route after a 5 second delay
  routingContext.vertx().setTimer(5000, tid ->  routingContext.next());
});

Route route3 = router.route("/some/path/").handler(routingContext -> {

  HttpServerResponse response = routingContext.response();
  response.write("route3");

  // Now end the response
  routingContext.response().end();
});

In the above example route1 is written to the response, then 5 seconds laterroute2 is written to the response,then 5 seconds laterroute3 is written to the response and the response is ended.

Note, all this happens without any thread blocking.

Using blocking handlers

Sometimes, you might have to do something in a handler that might block the event loop for some time, e.g. calla legacy blocking API or do some intensive calculation.

You can’t do that in a normal handler, so we provide the ability to set blocking handlers on a route.

A blocking handler looks just like a normal handler but it’s called by Vert.x using a thread from the worker poolnot using an event loop.

You set a blocking handler on a route with blockingHandler.Here’s an example:

router.route().blockingHandler(routingContext -> {

  // Do something that might take some time synchronously
  service.doSomethingThatBlocks();

  // Now call the next handler
  routingContext.next();

});

By default, any blocking handlers executed on the same context (e.g. the same verticle instance) areordered - thismeans the next one won’t be executed until the previous one has completed. If you don’t care about orderering anddon’t mind your blocking handlers executing in parallel you can set the blocking handler specifyingordered asfalse usingblockingHandler.

Routing by exact path

A route can be set-up to match the path from the request URI. In this case it will match any request which has a paththat’s the same as the specified path.

In the following example the handler will be called for a request /some/path/. We also ignore trailing slashesso it will be called for paths/some/path and/some/path// too:

Route route = router.route().path("/some/path/");

route.handler(routingContext -> {
  // This handler will be called for the following request paths:

  // `/some/path`
  // `/some/path/`
  // `/some/path//`
  //
  // but not:
  // `/some/path/subdir`
});

Routing by paths that begin with something

Often you want to route all requests that begin with a certain path. You could use a regex to do this, but a simplyway is to use an asterisk* at the end of the path when declaring the route path.

In the following example the handler will be called for any request with a URI path that starts with/some/path/.

For example /some/path/foo.html and /some/path/otherdir/blah.css would both match.

Route route = router.route().path("/some/path/*");

route.handler(routingContext -> {
  // This handler will be called for any path that starts with
  // `/some/path/`, e.g.

  // `/some/path`
  // `/some/path/`
  // `/some/path/subdir`
  // `/some/path/subdir/blah.html`
  //
  // but not:
  // `/some/bath`
});

With any path it can also be specified when creating the route:

Route route = router.route("/some/path/*");

route.handler(routingContext -> {
  // This handler will be called same as previous example
});

Capturing path parameters

It’s possible to match paths using placeholders for parameters which are then available in the requestparams.

Here’s an example

Route route = router.route(HttpMethod.POST, "/catalogue/products/:productype/:productid/");

route.handler(routingContext -> {

  String productType = routingContext.request().getParam("producttype");
  String productID = routingContext.request().getParam("productid");

  // Do something with them...
});

The placeholders consist of : followed by the parameter name. Parameter names consist of any alphabetic character,numeric character or underscore.

In the above example, if a POST request is made to path: /catalogue/products/tools/drill123/ then the route will matchandproductType will receive the valuetools and productID will receive the valuedrill123.

Routing with regular expressions

Regular expressions can also be used to match URI paths in routes.

Route route = router.route().pathRegex(".*foo");

route.handler(routingContext -> {

  // This handler will be called for:

  // /some/path/foo
  // /foo
  // /foo/bar/wibble/foo
  // /foo/bar

  // But not:
  // /bar/wibble
});

Alternatively the regex can be specified when creating the route:

Route route = router.routeWithRegex(".*foo");

route.handler(routingContext -> {

  // This handler will be called same as previous example

});

Capturing path parameters with regular expressions

You can also capture path parameters when using regular expressions, here’s an example:

Route route = router.routeWithRegex(".*foo");

// This regular expression matches paths that start with something like:
// "/foo/bar" - where the "foo" is captured into param0 and the "bar" is captured into
// param1
route.pathRegex("\\/([^\\/]+)\\/([^\\/]+)").handler(routingContext -> {

  String productType = routingContext.request().getParam("param0");
  String productID = routingContext.request().getParam("param1");

  // Do something with them...
});

In the above example, if a request is made to path: /tools/drill123/ then the route will matchandproductType will receive the valuetools and productID will receive the valuedrill123.

Captures are denoted in regular expressions with capture groups (i.e. surrounding the capture with round brackets)

Routing by HTTP method

By default a route will match all HTTP methods.

If you want a route to only match for a specific HTTP method you can use method

Route route = router.route().method(HttpMethod.POST);

route.handler(routingContext -> {

  // This handler will be called for any POST request

});

Or you can specify this with a path when creating the route:

Route route = router.route(HttpMethod.POST, "/some/path/");

route.handler(routingContext -> {

  // This handler will be called for any POST request to a URI path starting with /some/path/

});

If you want to route for a specific HTTP method you can also use the methods such asget,post andput named after the HTTPmethod name. For example:

router.get().handler(routingContext -> {

  // Will be called for any GET request

});

router.get("/some/path/").handler(routingContext -> {

  // Will be called for any GET request to a path
  // starting with /some/path

});

router.getWithRegex(".*foo").handler(routingContext -> {

  // Will be called for any GET request to a path
  // ending with `foo`

});

If you want to specify a route will match for more than HTTP method you can callmethodmultiple times:

Route route = router.route().method(HttpMethod.POST).method(HttpMethod.PUT);

route.handler(routingContext -> {

  // This handler will be called for any POST or PUT request

});

Route order

By default routes are matched in the order they are added to the router.

When a request arrives the router will step through each route and check if it matches, if it matches thenthe h

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值