vertx web开发(二)

本文介绍了如何基于Vert.x和Kotlin构建动态路由注册工厂,模仿SpringMVC的注解方式,定义了@Controller和@Route注解,通过反射实现路由的自动注册和HTTP请求拦截。通过这种方式,可以方便地管理和组织HTTP路由,同时提供了权限检查、参数校验和阻塞请求处理等功能。示例展示了如何创建一个简单的控制器并注册路由,使得访问特定URL时能返回预设的响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 前言

上文介绍了vertx的基本用法,并且结合kotlin的特性,为future写了几个比较有用的扩展函数,本文将主要为vertx web开发的路由进行探索。

  • Route初使用

在官方文档中,引进包 ‘io.vertx:vertx-web:3.4.2’,即可获取路由能力,从官方的例子如下代码:

router.route("/some/path/").handler(routingContext -> {
  HttpServerResponse response = routingContext.response();
  response.setChunked(true);
  response.write("route1\n");
  routingContext.next()
});
router.route("/some/path/").handler(routingContext -> {
  HttpServerResponse response = routingContext.response();
  response.write("route2\n");
   routingContext.next()
});
 router.route("/some/path/").handler(routingContext -> {
  HttpServerResponse response = routingContext.response();
  response.write("route3");
  routingContext.response().end();
});

从这个例子中我们可以得出结论:在访问/some/path路径的时候,route会依次被访问,next表示下个route将被执行,直到请求end.根据router这个特性,并且换一个思路,可以将route看成http请求的拦截器,在借助反射的可以实现一个简单路由注册工厂。

  • 路由工厂实现

这里借助一下springMVC的路由结构,首先先定义一个@Controller的注解,标明这个类是个控制器,在定义一下@Route注解,表示是一个路由。其定义如下:


@Target(AnnotationTarget.CLASS)
annotation class Controller(val path:String = "")

@Target(AnnotationTarget.FUNCTION)
annotation class Route(val path:String,
                       val method: HttpMethodEnum = HttpMethodEnum.POST,
                       // 是否授权 检查
                       val isAuthority:Boolean = false,
                       // 对上传参数进行 dto validate校验,此处填写dto 全部报名
                       val dto:String = "",
                       // 是否会堵塞 请求
                       val isBlock:Boolean = false,
                      )

在定义这两个注解后,后面去路由工厂的实现就是找Controller,以及下面的Route,其实现过程如下:

 /**
  * 加载包里面的路由
  * @param package: cn.demo.controller.*
  */
 private val router = Router.router(vertx)
 suspend fun<T> registerRoute(package:String){
           val last = package.lastIndexOf(".")
           val path =   package.substring(0,last).replace(".","/")
          // 加载包路径
           val root = clazz.classLoader.getResource("")?.path?:""
           val paths = vertx.fileSystem().readDir(root + path).await()
           if ( package.last() == '*'){
  			       if (file.endsWith(".class") && !file.contains("$")){
                        var name = file.substring(file.lastIndexOf("/")+1,file.lastIndexOf("."))
                        if (name.contains("\\")) name = name.substringAfterLast("\\")
                        val clsName = path.replace("/",".")+"."+name
                        val newClazz = Class.forName(clsName)
                        val annotation = newClazz.getAnnotation(Controller::class.java)
                        // 获取每个route方法
                        val methods = newClazz.declaredMethods.filter { method -> method.annotations.map { it.annotationClass }.toList().contains(Route::class) }
                           methods.forEach { method ->
                            val obj = newClazz.newInstance()
                            val url = annotation?.path ?: ""
                            val controller = method.getAnnotation(Route::class.java) ?: throw Exception("@route not exist")
  							// 从这里开始为请求注册路由
  							 if (controller.isAuthority) router.route(HttpMethod(controller.method.name),url + controller.path).handler{ handle -> RouteIntercept.auth(handle) }
                            if (controller.dto != "" ) router.route(HttpMethod(controller.method.name),url + controller.path).handler(RouteIntercept.validate(controller.dto))
                            if (controller.isBlock) router.route(HttpMethod(controller.method.name),url + controller.path).blockingHandler{context ->method.invoke(obj,context)} 
                            else router.route(HttpMethod(controller.method.name),url + controller.path).handler{context ->method.invoke(obj,context)   } 
         }
     }

}

注意以上的 registerRoute 方法是suspend的,也就说这个方法在必须异步执行,也就是说必须在kotlin协程或者线程里面执行,这里强烈推荐com.github.isyscore:common-jvm:1.6.1包,这里面开携程只要一个go函数,就可以轻松开一个携程,因此其结果为:

    go{
    registerRoute("com.demo.controller.*")
    }

此方法会异步注册路由,当然不要忘记将router挂到vertx的HttpServer上。

  • 实现效果

通过以上的路由工厂的注册路由,可以像springMVC一样轻松写一个控制器,例如:

@Controller
class IndexRouter {
    @Route("/index", HttpMethodEnum.GET)
    fun index(ctx: RoutingContext){
         ctx.response().end("hello world!!")
    }
}

通过访问http://127.0.0.1:8080/index 即可。

  • 结语

本篇通过vertx 的route注册的机制进行改造,从而实现了route注册工厂,使得将路由与注册进行了剥离,同时根据route的顺序执行性,对请求的拦截也进行了基本的实现。下文将继续对vertx数据访问进行探索。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

myenjoy_1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值