Vert.x . В этом посте рассказывается, как изящно и просто публиковать веб-сервисы Rest.
Как и в предыдущем посте, представлены примеры на Java и Scala, исходный код размещен на GitHub как часть lang-scala https://github.com/ouertani/vert.x/tree/master/vertx-lang/vertx-. Ланг-Скала
I- Resticle
Resticle — это единица развертывания, посвященная отдыху . Он предоставляет новый метод («дескрипторы»), который может использоваться Vert.x для запуска служб Rest. «Handles» возвращает последовательность обработчиков отдыха:
- RestHandler: Action => Ответ
- Действие:
- GET (рисунок: строка)
- POST (шаблон: строка)
- PUT (рисунок: строка)
- УДАЛИТЬ (рисунок: строка)
- ГОЛОВА (рисунок: Строка)
- ВСЕ (образец: строка)
- Ответ: HttpServerRequest => Любой
- ОК, Несанкционированный, ….
В этом уроке мы будем работать с классом SampleResticle для scala и java.
II — Hello World
Vert.x предоставляет мощный механизм маршрутизации и сопоставления маршрутов , который упрощает маршрутизацию HTTP-запросов к различным обработчикам на основе сопоставления с шаблоном в пути запроса.
В фрагменте Hello World давайте опубликуем статический сервис GET:
- ПОЛУЧИТЬ: / привет → код: 200, тело: мир
Scala
class SampleResticle extends Resticle { override def handles = { GET("/hello") :> OK( _ => "world ") } }
Ява
public class SampleResticle extends Verticle { public void start() { HttpServer server = vertx.createHttpServer(); RouteMatcher routeMatcher = new RouteMatcher(); routeMatcher.get("/hello", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; req.response.end("world"); } }); server.requestHandler(routeMatcher).listen(8080, "localhost"); } }
III- Цепные погрузчики
Используя Resticle, мы можем легко завершить работу обработчиков цепочек. Следующие фрагменты создают статические сервисы GET и DELETE:
- ПОЛУЧИТЬ: / привет → код: 200, тело: мир
- УДАЛИТЬ: / posts → код: 401, тело: не разрешено пользователю
Scala
class SampleResticle extends Resticle { override def handles = { GET("/hello") :> OK( _ => "world ") } ++ { DELETE("/posts") :> Unauthorized {_ => "Not allowed user" }} }
Ява
public class SampleResticle extends Verticle { public void start() { HttpServer server = vertx.createHttpServer(); RouteMatcher routeMatcher = new RouteMatcher(); routeMatcher.get("/hello", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; req.response.end("world"); } }); routeMatcher.delete("/posts", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =401; req.response.end("Not allowed user"); } }); server.requestHandler(routeMatcher).listen(8080, "localhost"); } }
IV — Ценность пути
Сопоставление с образцом Vert.x позволяет извлечь значения из пути и использовать их в качестве параметров в запросе.
- ПОЛУЧИТЬ: / привет → код: 200, тело: мир
- УДАЛИТЬ: / posts → код: 401, тело: не разрешено пользователю
- POST: /: blogname → code: 200, body: post {blogname} получено!
Scala: (с использованием строковой интерполяции )
class SampleResticle extends Resticle { override def handles = { GET("/hello") :> OK( _ => "world ") } ++ { DELETE("/posts") :> Unauthorized {_ => "Not allowed user" }} ++ { POST("/:blogname") :> OK {req => val param = req.params().get("blogname") ; s"post $param received !" } } }
Ява
public class SampleResticle extends Verticle { public void start() { HttpServer server = vertx.createHttpServer(); RouteMatcher routeMatcher = new RouteMatcher(); routeMatcher.get("/hello", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; req.response.end("world"); } }); routeMatcher.delete("/posts", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =401; req.response.end("Not allowed user"); } }); routeMatcher.post("/:blogname", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; String blogName = req.params().get("blogname"); req.response.end("post "+blogName+ " received !"); } }); server.requestHandler(routeMatcher).listen(8080, "localhost"); } }
V- Json
Предположим, у нас есть класс Blog с двумя строковыми полями title и content:
case class Blog (title :String , content : String)
Java-эквивалент был перемещен в конец документа из-за его многословия;).
Публикация объекта с использованием Resticle проста и прозрачна благодаря неявному конвертеру: T => Buffer.
Скала (Тип Класс)
object Blog { implicit def toBuffer(blog : Blog):Buffer = JsonObject.withString("title" -> blog.title).withString("content" -> blog.content) }
Java (с явным конвертором)
public class Convertor { public static JsonObject toJson(Blog blog) { return new JsonObject().putString("title", blog.getTitle()).putString("content", blog.getContent()); } }
- ПОЛУЧИТЬ: / привет → код: 200, тело: мир
- УДАЛИТЬ: / posts → код: 401, тело: не разрешено пользователю
- POST: /: blogname → code: 200, body: post {blogname} получено!
- GET: /: id → code: 200, body: {«title»: «rest», «content»: «scala & vertx»}
Scala
class SampleResticle extends Resticle { override def handles = { GET("/hello") :> OK( _ => "world ") } ++ { DELETE("/posts") :> Unauthorized {_ => "Not allowed user" }} ++ { POST("/:blogname") :> OK {req => val param = req.params().get("blogname") ; s"post $param received !" } } ++ { GET("/:id") :> OK ( _ => Blog("rest","scala & vertx"))} }
Ява
public class SampleResticle extends Verticle { public void start() { HttpServer server = vertx.createHttpServer(); RouteMatcher routeMatcher = new RouteMatcher(); routeMatcher.get("/hello", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; req.response.end("world"); } }); routeMatcher.delete("/posts", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =401; req.response.end("Not allowed user"); } }); routeMatcher.post("/:blogname", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; String blogName = req.params().get("blogname"); req.response.end("post "+blogName+ " received !"); } }); routeMatcher.get("/:id", new Handler<HttpServerRequest>() { public void handle(HttpServerRequest req) { req.response.statusCode =200; Blog blog = new Blog("rest","scala & vertx"); JsonObject obj = Convertor.toJson(blog); req.response.end(obj.encode()); } }); server.requestHandler(routeMatcher).listen(8080, "localhost"); } }
Блог Java
public class Blog { private final String title; private final String content; public Blog(String title, String content) { this.title = title; this.content = content; } public String getTitle() { return title; } public String getContent() { return content; } }
Вывод
Несмотря на то, что Resticle находится на первом этапе разработки, поддержка Rest намного проще и элегантнее в Scala, чем в Java. Как описано в первом уроке, Java-версия Vert.x обременена пугающим количеством обработчиков. Будет ли Vert.x 2.0 решать эту проблему с помощью API Promises / Deferred ?