我如何减少 vert.x 中的样板代码量
How can i reduce amount of boilerplate code in vert.x
我已经阅读了一些关于 vertx.io 的教程,但我仍然无法理解如何最大限度地减少重复代码。
例如,我需要实现 RESTful 从数据库获取数据的服务。我已经为表(客户、管理员)准备了 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 类.
能否分享您的示例或展示如何更改我的方法?
VertX 不是一个框架,这使得一些开发人员可以轻松设计自己的结构,但对于某些开发人员来说,它却成为噩梦。你正在寻找的是一个预先设计的框架,它已经准备好路由器、控制器、数据库连接。显然这不是 vertx 的意思,它更像是一个库,按你想要的方式扩展它。
我在您的代码中看到,对于每个服务功能,您都获得了 SQL 连接。如果您使用过 Spring 等其他框架,则可以使用 DI 连接。
您需要实现 DI,一些 MVC 设计,然后您的样板代码将被删除。
我做过类似的事情,但 MongoDB。
这是例子
1。首先部署 Verticle
/**
* 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());
}
});
}
我已经阅读了一些关于 vertx.io 的教程,但我仍然无法理解如何最大限度地减少重复代码。
例如,我需要实现 RESTful 从数据库获取数据的服务。我已经为表(客户、管理员)准备了 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 类.
能否分享您的示例或展示如何更改我的方法?
VertX 不是一个框架,这使得一些开发人员可以轻松设计自己的结构,但对于某些开发人员来说,它却成为噩梦。你正在寻找的是一个预先设计的框架,它已经准备好路由器、控制器、数据库连接。显然这不是 vertx 的意思,它更像是一个库,按你想要的方式扩展它。
我在您的代码中看到,对于每个服务功能,您都获得了 SQL 连接。如果您使用过 Spring 等其他框架,则可以使用 DI 连接。 您需要实现 DI,一些 MVC 设计,然后您的样板代码将被删除。
我做过类似的事情,但 MongoDB。
这是例子
1。首先部署 Verticle
/**
* 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());
}
});
}