Skip to content
B1o0dy_Trey edited this page Feb 28, 2020 · 20 revisions

Route是festival-web核心功能之一,在编写Web服务的时候,首先需要的就是声明一个路由。路由本身是一个由@RouteController注解标注的一个类,一个类一旦被@RouteController注解标注,那么便可以将Web请求映射到其拥有的方法上。

mapping

为了将请求映射到路由类的方法上,可以在路由类的方法上使用@RouteMapping注解来声明一个请求映射。使用@RouteMapping声明一个映射方法时,必须传入一个映射地址以及相应的Http请求方法。以下代码展示了@RouteMapping的使用方式。

@Singleton
@RouteController
public class HelloController {
    
    //hello方法最终的请求路径是/hello
    @RouteMapping(value = "/hello",method = HttpMethod.GET)
    public String hello() {
        return "hello festival";
    }
}

除了定义映射方法之外,@RouteMapping也可以注解在路由类上,表示父路径,注解在路由类上的@RouteMapping不需要设置请求方法。使用方式如下:

@Singleton
@RouteMapping("/parent")
@RouteController
public class HelloController {
    
    //hello方法最终的请求路径是/parent/hello
    @RouteMapping(value = "/hello",method = HttpMethod.GET)
    public String hello() {
        return "hello festival";
    }
}

映射方法的返回值会返回给前端,对于复杂对象会以json的形式返回。如果方法没有返回值,则需要用户自行处理请求的响应,这需要用户获取请求的上下文RoutingContext来实现。

rest

使用@RouteMapping可以声明一个映射方法,但每次都需要指定请求方式,未免太过麻烦,且不利于编写rest风格的路由。为了解决这个问题,可以使用@RouteMapping的子注解@GetMapping、@PostMapping、@PutMapping、@DeleteMapping。这4类注解分别对应了Http的4种请求,使用方式如下:

@Singleton
@RouteController
public class UserController {

    @GetMapping("/hello")
    public String hello() {
        return "hello festival";
    }
    
    @PostMapping("/hello")
    public String hello() {
        return "hello festival";
    }
    
    @PutMapping("/hello")
    public String hello() {
        return "hello festival";
    }
    
    @DeleteMapping("/hello")
    public String hello() {
        return "hello festival";
    }
    
}

context

WebServer对于每一个请求,都会创建一个RoutingContext,代表请求的上下文,通过RoutingContext可以获取所有的请求数据以及对请求作出一些响应,具体可以参考Vertx-Web的相关问题。RoutingContext的获取,可以通过在路由方法上声明一个RoutingContext来实现,RoutingContext的实例将自动注入到方法上。

@GetMapping("/testContext")
public void test(RoutingContext routingContext) {
    ...
}

获取了RoutingContext之后,可以通过RoutingContext对Http请求和响应做多种操作:

  • 获取请求参数
    MultiMap queryParams = routingContext.queryParams();
  • 获取HTTP请求对象及其数据
    HttpServerRequest request = routingContext.request();
    MultiMap formAttributes = request.formAttributes();
    MultiMap headers = request.headers();
    String path = request.path();
    HttpConnection connection = request.connection();
  • 文件上传
    for (FileUpload fileUpload : routingContext.fileUploads()) {
        ...
    }
  • 获取并设置HTTP响应对象
    routingContext.response()
        .putHeader("content-type", "text/plain")
        .end("Hello World from Vert.x-Web!");

更多RoutingContext用法请参考RoutingContext文档、HttpServerRequest文档[HttpServerResponse文档]、(https://vertx.io/docs/apidocs/io/vertx/reactivex/core/http/HttpServerResponse.html)。

custom

如果想要直接获取Router对象来配置路由,可以定义一个可被容器扫描的Bean类并且实现RouterAware接口,WebContext在处理此类bean的时候会通过调用此bean的setRouter(Router router)方法将webServer的Router对象传入这个bean,拿到Router对象后,我们可以对路由进行个性化配置。配置方法详见vertx中关于Router和Route的介绍及Router API文档和Route API文档。

Example:

@Named
public class RouterConfiguration implements RouterAware {

    Router router;

    @Override
    public void setRouter(Router router) throws BeansException {
        this.router = router;
        router.route(HttpMethod.GET, "/costom").handler(routingContext -> {
            routingContext.response().end("Hello");
        });
    }
}

访问 http://localhost:8083/costom 获得结果Hello。

除了直接获取Router对象来添加自定义路由的方式之外,还可以通过向容器注入RouteAttribute实例来添加自定义路由,这也是推荐的方式。通过注入RouteAttribute添加的路由,可以被Filter拦截。使用方式如下:

@Singleton
@Named("route1")
public RouteAttribute customRoute() {
    return RouteAttribute.builder()
            .httpMethod(HttpMethod.GET)
            .url("/custom")
            .contextHandler(routingContext -> {
                routingContext.response().end("test custom!");
            })
            .build();
}

produces

consumes

cors

timeout

static

template

festival框架提供对几种模板引擎的支持,包括Jade、Freemarker、Thymeleaf。有关这三种模板引擎的写法请查阅官方文档。

要想在框架中启用模板引擎,您需要在application.yaml中设置:

server:
    template:
        enable: true

或者在application.properties中设置:

server.template.enable = true

在配置文件中,template有如下属性:

  • enable:是否启用模板引擎。
  • type:设置模板引擎类型,可以设置的属性有"freemarker"、"thymeleaf"、"jade"。(必选)
  • cache.enable:设置是否启用缓存,默认为开。
  • path:设置读取模板引擎路径,默认为“src/main/resources/template”。
  • suffix:设置模板引擎文件后缀。(必选)

ModelAndView

ModelAndView通常在controller中,作为返回值使用,于向客户端返回模型和视图。

ModelAndView有如下两个构造方法:

  • ModelAndView(String view):
    • view:指定模板引擎的文件名称(不包括文件名后缀)
  • ModelAndView(String view, Map<String, Object> model):
    • view:指定模板引擎的文件名称(不包括文件名后缀)
    • model:为ModelAndView设置model

使用add()方法可以为model添加属性。

下面是一个使用ModelAndView的例子:

@Singleton
@RouteController
public class example{
    @GetMapping("/modelandview")
    public ModelAndView exampleModelAndView() {
        ModelAndView modelAndView = new ModelAndView("template");
        modelAndView.add("hello", "hello modelandview");
        return modelAndView;
    }
}

Thymeleaf

要使用Thymeleaf,您需要在项目中添加以下依赖项: io.vertx:vertx-web-templ-thymeleaf:${version}。

Thymeleaf可以直接使用ModelAndView中model的属性。

下面是一个例子:

<p th:text="${hello}"></p>

我们将看到:

hello modelandview

FreeMarker

要使用FreeMarker,您需要在项目中添加以下依赖项: io.vertx:vertx-web-templ-freemarker:${version}

FreeMarker可以直接使用ModelAndView中model的属性。

下面是一个例子:

${hello}

我们将看到:

hello modelandview

Jade

要使用Jade,您需要在项目中添加以下依赖项: io.vertx:vertx-web-templ-jade: ${version}

Jade可以直接使用ModelAndView中model的属性。

下面是一个例子:

div !{hello}

我们将看到:

hello modelandview

Clone this wiki locally