Vert.x 4 服务代理(Service Proxy)

编程教程 > Java > Vert.x (331) 2024-11-26 14:39:04

前言

vert.x 默认是没有像spring的依赖注入的,需要自己结合vertx-service-proxy插件可以实现类似的效果。本文引用项目为基础《Vert.x 4 Web应用初识

 

环境

  • JDK 17
  • Vert.x 版本 4.5.9
  • Maven

引入必要依赖

maven pom.xml 引入依赖

<!--服务代理-->
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-service-proxy</artifactId>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-codegen</artifactId>
<scope>provided</scope>
<classifier>processor</classifier>
</dependency>

<!--反射工具-->
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>${reflections.version}</version>
</dependency>
<!--/服务代理-->

 

提示:JDK 17环境+idea 环境引入上方配置后无需在build->maven-compiler-plugin插件增加配置即可使用。反而因为配置了annotationProcessor会导致报错,但是可以通过下面配置进行修改默认的生成代码路径

<generatedSourcesDirectory>
${project.basedir}/src/main/generated
</generatedSourcesDirectory>
<compilerArgs>
<arg>-AoutputDirectory=${project.basedir}/src/main</arg>
</compilerArgs>

修改了路径记得把清理插件配置上,清理这个路径

<!-- 删除生成的文件 -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filesets>
<fileset>
<directory>${project.basedir}/src/main/generated</directory>
</fileset>
</filesets>
</configuration>
</plugin>

 

默认插件生成的代理源码在这里

Vert.x 4 服务代理(Service Proxy)_图示-62b4b95d0598453f977b90661beef660.png

并且源码提示不要修改

Vert.x 4 服务代理(Service Proxy)_图示-a80e04ec38ff4fa8b1a8395ef30d9f67.png

所以,默认最好,不要修改generated的代码输出位置!!!!

 

 

项目结构

Vert.x 4 服务代理(Service Proxy)_图示-a12ef6eb8b834cbf8c456f709148c786.png

 

服务编写

 

服务接口编写

UserService

代码聚焦

@ProxyGen
public interface UserService {
/**
* 根据id获取用户信息
* @param id 用户id
* @param handler 一部处理
*/
void getUserById(Integer id, Handler<AsyncResult<JsonObject>> handler);
}

 

创建包信息【必须】

vertx service proxy 必须创建包信息指定services(服务层)所在包,因为需要编译时候生成一些代码。

Vert.x 4 服务代理(Service Proxy)_图示-f867cb74ecba46bb8b04d9e84e87c34f.png

 

在Service这个包下面创建包信息 package-info.java

内容如下:

@ModuleGen(name = "proxy",groupPackage = "com.demo.vertx.vertx_demo.service")
package com.demo.vertx.vertx_demo.service;

import io.vertx.codegen.annotations.ModuleGen;
 

说明:

  • 单模块项目 :name-名称随便取一个满足命名规范即可(暂时只用到一个),groupPackage 包配置到service层的包即可。
  • 多模块项目:name  记得不重复,groupPackage - 每个模块的service包路径即可

 

基础service创建

基础service提供了一些每个service都有的方法,就好比spring时代的BaseController之类的效果。

AbstractAsyncService 代码参考:

@Slf4j
public abstract class AbstractAsyncService {

/**
* 服务注册地址
* @return 注册地址
*/
public String registerAddress(){
String className = this.getClass().getName();
return className.substring(0, className.lastIndexOf("Impl")).replace(".impl", "");
}

/**
* 获取注册接口类
* @return 获取注册接口类
* @throws ClassNotFoundException 异常
*/
@SuppressWarnings({"rawtypes"})
public Class registerInterface() throws ClassNotFoundException {
String className = this.getClass().getName();
return Class.forName(className.substring(0, className.lastIndexOf("Impl")).replace(".impl", ""));
}

/**
* 异常处理
* @param throwable 异常
* @param handler 处理器
* @param <T> 泛型入参
*/
protected <T> void handlerException(Throwable throwable, Handler<AsyncResult<T>> handler){
log.error(throwable.getMessage(), throwable);
handler.handle(ServiceException.fail(1, throwable.getMessage()));
}

}

主要三个方法,前两个是用来注册服务时候用的,最后一个是做了个通用异常处理。

提示:考虑到要用泛型,注册地址取巧直接使用的service全名(可能导致一个service接口多个实现类问题,但是一般也是一个对一个用)

 

服务接口实现

接口实现继承了AbstractAsyncService 和实现了用户服务

代码示例:

public class UserServiceImpl extends AbstractAsyncService implements UserService {

@Override
public void getUserById(Integer id, Handler<AsyncResult<JsonObject>> handler) {
if (id == null) {
handler.handle(Future.failedFuture("id is null"));
} else {
if (id < 0) {
handler.handle(Future.failedFuture("id is negative"));
}
JsonObject user = new JsonObject()
.put("id", id)
.put("name", "user")
.put("age", 20)
.put("gender", "male")
.put("birthday", "2023-01-01")
;
handler.handle(Future.succeededFuture(user));
}
}
}

 

服务注册和调用

服务注册

代码聚焦

/**
* 注册服务
* @param pageNames 扫描包路径下面的服务进行注册 eg:<code>com.demo.vertx.vertx_demo.service</code>
* <p>
* 更多参考:<a href="https://vertx.io/docs/vertx-service-proxy/java/">vertx-service-proxy</a>
* </p>
*
*/
@SuppressWarnings({"unchecked","rawtypes"})
private void registerServices(String pageNames){
Set<Class<? extends AbstractAsyncService>> services =
ReflectionUtils.getReflections(pageNames).getSubTypesOf(AbstractAsyncService.class);
ServiceBinder serviceBinder = new ServiceBinder(vertx);
if (!services.isEmpty()) {
try {
for (Class<? extends AbstractAsyncService> service : services) {
AbstractAsyncService serviceInstance = service.getDeclaredConstructor().newInstance();
//AbstractAsyncService#registerAddress获取注册地址/ID
//取巧:注册地址=接口全名
String registerAddress = (String) service.getMethod("registerAddress").invoke(serviceInstance);
//AbstractAsyncService#registerInterface获取注册类
Class registerInterfaceClass = (Class) service.getMethod("registerInterface").invoke(serviceInstance);
//注册
serviceBinder
.setAddress(registerAddress)
.register(registerInterfaceClass, serviceInstance);
}
} catch (Exception e) {
log.error("registerServices error : {}", e.getMessage());
}
}
}

通过泛型注册服务到vertx

 

服务调用
//获取用户服务(注意:必须先注册再拿注册服务要放到前面)
UserService userService = AsyncServiceUtils.getAsyncServiceInstance(UserService.class, vertx);

router.get("/user/:id").handler(ctx->{
String id = ctx.pathParam("id");
userService.getUserById(Integer.parseInt(id),ar->{
if(ar.succeeded()){
ctx.json(ar.result());
}else {
ctx.response()
.putHeader("content-type", "application/json")
.setStatusCode(500)
.end(ar.cause().getMessage());
}
});
});

 

启动项目,使用postman工具调用接口尝试

Vert.x 4 服务代理(Service Proxy)_图示-560884edba904ef1814fe693d6e6f269.png
入参 负数

入参为负数,返回结果提示id 是服务HTTP状态码500 与预期结果一致。

Vert.x 4 服务代理(Service Proxy)_图示-0a5669c6ce874c0793cd4d4e09afc676.png
正确入参

输入正确入参,返回服务模拟的数据,与预期结果一致。

 

至此我们完成了服务代理和服务调用的技能学习。

 

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
前言vert.x 默认是没有像spring的依赖注入的,需要自己结合vertx-service-proxy插件实现。本文引用项目为基础《Vert.x 4 Web
前言前面已经讲述了在vertx中,如何实现服务的注册和使用,这里主要讲解接口的暴露层,在vertx中如何实现类似Spring MVC的Controller层。项
前言Vert.x 中实现全局数据共享,如环境参数等。Vertx数据共享实现共享数据存入/更新SharedData sharedData = vertx.shar
前言这里主要讲解Vert.x配置文件的读取和使用,引用之前的项目《Vert.x 4 Web应用初识》 引入必要依赖maven pom.xml&lt;dependenc
前言最新的Ver.x 4 从idea工具运行启动,并访问。项目创建通过vert.x官网生成器完成。Vert.x 4项目创建打开vert.x官网项目生成地址,ht
前言项目由之前的第一个vert.x 4 项目改编而来,vert.x项目创建参考: vert.x 4 web应用编写修改MainVerticle文件,内容如下:p
Vert.x java 入门,Vert.x这个框架在常规的web业务开发中估计还不是很成熟。但是了解了他的一些原理我觉得可以有一番作为。今天主要简单讲解下eclipse Vert.x是什么有什么...
前言项目创建参考之前的《Vert.x 4 Web应用初识》。本文通过Vert.x实现了REST接口的CRUD操作。通过本教程你可以获得以下内容vert.x项目中
前言文件上传在web应用比较常见,本文以vert.x web实现文件上传功能。引用之前的项目《Vert.x 4 Web应用初识》作为基础,添加了日志。 Vert
前言Web项目开发一般接口入参都有校验需求,Vert.x 4 目前已有插件实现参数校验,引用之前的项目《Vert.x 4 Web应用初识》源码 引入验证插件ma
Vert.x 入门教程通过maven shade plugin插件打包发布项目,上一篇文章,我们主要初步的了解了下eclipse vert.x是什么有什么用。当然一个程序编写完成后最终还是需要打...
前言本文主要讲解在Vert.x环境下与Mysql数据库连接和操作,实现基础的增删改查和事务,以及REST接口返回数据库中查询结果。项目引用之前的《Vert.x
前言通过前面的学习,我们发现很多地方都需要使用到vertx的实例,本文讲述将实例初始化到一个保持类中,方便项目全局获取。 实例保持实现实现逻辑很简单,就是启动项
前言接上一篇《Vert.x 4 Web应用初识》,在web应用中除了访问地址得到动态的信息还有静态的资源库访问,如 jQuery / bootstrap 等前端
前言Vert.x Router路由中多个处理器之间通过RoutingContext共享数据实现。 Vert.x Router 上下文数据数据设置routingC