如何减少vert.x中样板代码的数量

时间:2017-03-02 13:52:35

标签: java reactive-programming vert.x event-driven

我已经阅读了vertx.io上的几个教程,但我仍然无法理解如何最大限度地减少重复代码。

例如,我需要实现从DB获取数据的RESTful服务。我为表(Customer,Administrator)和已实现的服务类准备了2个bean类:

AdministratorService.java

public void getAll(RoutingContext routingContext) {
    jdbc.getConnection(ar -> {
      SQLConnection connection = ar.result();
      connection.query(Queries.SELECT_ALL_ADMINS, result -> {
        List<Administrator> admins = result.result().getRows().stream().map(Administrator::new).collect(Collectors.toList());
        routingContext.response()
          .putHeader("content-type", "application/json; charset=utf-8")
          .end(Json.encodePrettily(admins));
        connection.close();
      });
    });
  }

  public void getOneById(RoutingContext routingContext) {
    final String id = routingContext.request().getParam("id");
    if (id == null) {
      routingContext.response().setStatusCode(400).end();
    } else {
      jdbc.getConnection(ar -> {
        // Read the request's content and create an instance of Administrator.
        SQLConnection connection = ar.result();
        select(id, connection, Queries.SELECT_ONE_ADMIN_BY_ID, result -> {
          if (result.succeeded()) {
            routingContext.response()
              .setStatusCode(200)
              .putHeader("content-type", "application/json; charset=utf-8")
              .end(Json.encodePrettily(result.result()));
          } else {
            routingContext.response()
              .setStatusCode(404).end();
          }
          connection.close();
        });
      });
    }
  }

CustomerService.java

public void getAll(RoutingContext routingContext) {
    jdbc.getConnection(ar -> {
      SQLConnection connection = ar.result();
      connection.query(Queries.SELECT_ALL_CUSTOMERS, result -> {
        List<Customer> customers = result.result().getRows().stream().map(Customer::new).collect(Collectors.toList());
        routingContext.response()
          .putHeader("content-type", "application/json; charset=utf-8")
          .end(Json.encodePrettily(customers));
        connection.close();
      });
    });
  }


  public void getOneById(RoutingContext routingContext) {
    final String id = routingContext.request().getParam("id");
    if (id == null) {
      routingContext.response().setStatusCode(400).end();
    } else {
      jdbc.getConnection(ar -> {
        // Read the request's content and create an instance of Administrator.
        SQLConnection connection = ar.result();
        select(id, connection, Queries.SELECT_ONE_CUSTOMER_BY_ID, result -> {
          if (result.succeeded()) {
            routingContext.response()
              .setStatusCode(200)
              .putHeader("content-type", "application/json; charset=utf-8")
              .end(Json.encodePrettily(result.result()));
          } else {
            routingContext.response()
              .setStatusCode(404).end();
          }
          connection.close();
        });
      });
    }
  }

不难看出那部分

.routingContext.response()
.putHeader("content-type", "application/json; charset=utf-8")
每种方法都重复

。一般来说,这些类之间的所有区别都是sql请求和bean类。

您可以分享您的示例或演示如何更改我的方法吗?

2 个答案:

答案 0 :(得分:3)

VertX不是一个框架,这使得一些开发人员可以轻松地设计自己的结构,但对于某些人而言,它变成了噩梦。您正在寻找的是一个预先设计的框架,可以使用路由器,控制器和数据库连接。显然,不是vertx,它更像是一个库,可以按照你想要的方式扩展它。

我在您的代码中看到,对于每个Service函数,您都会获得SQL连接。如果您已经使用过Spring之类的其他框架,则可以使用DI进行连接。 您需要实现DI,一些MVC设计,然后您的样板代码将被删除。

我做了类似的事情,但对于MongoDB。

VertX with MongoDB

答案 1 :(得分:0)

这是示例

1。首先部署垂直线

/**
* deploy verticle
*/ 
@PostConstruct
public void deployVerticle() {
    Vertx vertx = Vertx.vertx();
    log.info("deply vertx start...... ");
    vertx.deployVerticle(dbVerticle);
    DeploymentOptions options = new DeploymentOptions();
    options.setInstances(4);
    StaticServer.setApplicationContext(context);
    vertx.deployVerticle(StaticServer.class.getName(), options);
    log.info("deply vertx end...... ");
}

2。第二个StaticServer注入路由器

@Override
public void start() throws Exception {
    Map<String, Api> apis = applicationContext.getBeansOfType(Api.class);
    JavaConfig javaConfig = applicationContext.getBean(JavaConfig.class);
    Router router = Router.router(vertx);
    apis.forEach((k, v) -> RouterUtils.injectRouter(v, router));
    vertx.createHttpServer().requestHandler(router).listen(javaConfig.httpPort());
}
public static void injectRouter(Api api, Router router) {
        Map<Method, RequestMapping> annotatedMethods = MethodIntrospector.selectMethods(api.getClass(), (MetadataLookup<RequestMapping>) 
                method -> AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class));
        RequestMapping annotatedClass = api.getClass().getDeclaredAnnotation(RequestMapping.class);
        annotatedMethods.forEach((method, request) -> {
            Class<?>[] params = method.getParameterTypes();
            Assert.isAssignable(RoutingContext.class, params[0]);
            router.route(request.method(), annotatedClass.value() + request.path()).handler(context -> {
                try {
                    context.response().putHeader("content-type", "application/json; charset=utf-8");
                    method.invoke(api, context);
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    log.error("e :", e.getCause());
                }
            });
        });
    }

3。最后一次发布查询事件

@RequestMapping("/")
public void root(RoutingContext context) {
    JsonObject query = new JsonObject();
    query.put("sql", "select * from user where username = ?");
    query.put("params", (new JsonArray()).add("zhengfc"));
    context.vertx().eventBus().request("db.query", query, ar -> {
        if (ar.succeeded()) {
            context.response().end(ar.result().body().toString());
        } else {
            log.error("db.query failed: {}", ar.cause());
        }
    });
}