Hapi 的路由和控制器使用详解

Hapi 是一款非常流行的 Node.js 框架,其具有出色的插件系统和构建 API 的能力。在使用 Hapi 构建一款应用时,路由和控制器是非常重要的组成部分。本文将详细介绍 Hapi 路由和控制器的使用。

路由

路由是管理 URL 路径、HTTP 动词和处理程序之间关系的机制。在 Hapi 中定义路由可以使用 route 的配置项。

以下是一个简单的路由示例:

server.route({
  method: 'GET',
  path: '/',
  handler: (request, h) => {
      return 'Hello World!';
  }
});

这个路由将会监听根 URL,使用 GET 请求,并返回字符串 Hello World!

路由参数

在一些情况下,我们需要使用 URL 参数以优雅地处理动态路由。Hapi 支持三种不同类型的动态路由参数:path,query 和 payload。

Path 参数

Path 参数是从 URL 中提取的参数,可以使用花括号括起来,如下所示:

server.route({
  method: 'GET',
  path: '/user/{id}',
  handler: (request, h) => {
      const id = request.params.id;
      return `Hi, user ${id}!`;
  }
});

在这个例子中,我们定义了一个 path 参数 id,可以通过访问 /user/1 来获取用户 1 的信息。

Query 参数

Query 参数是从 URL 中提取的参数,位于问号字符 (?) 之后,并且以 key=value 的形式存储。在 Hapi 中可以通过 request.query 来得到所有的 query 参数。

server.route({
  method: 'GET',
  path: '/user',
  handler: (request, h) => {
      const query = request.query;
      const id = query.id;
      return `Hi, user ${id}!`;
  }
});

在这个例子中,我们定义了一个 query 参数 id,可以通过访问 /user?id=1 来获取用户 1 的信息,注意,question mark(?) 后的查询参数是由 hapi router 的解析器解析的。

Payload 参数

除了从 URL 中提取参数,我们还可以从请求的负载中提取参数。Hapi 通过将负载解析为 JSON 对象(如果存在)来获取这些参数。

server.route({
  method: 'POST',
  path: '/user',
  handler: (request, h) => {
      const data = request.payload;
      const name = data.name;
      const age = data.age;
      return `Hi, my name is ${name}. I am ${age} years old.`;
  }
});

在这个例子中,我们定义了一个负载参数 nameage,可以通过访问 POST /user 并提供 JSON 负载数据 {"name": "Zhang San", "age": 18} 来创建一个新用户。

路由装饰器

Hapi 也支持使用路由装饰器来定义路由,这是一种更加优雅的方式。框架提供了多个装饰器,包括 @route@GET@POST 等。这里以 @route 装饰器为例:

@route({
  method: 'GET',
  path: '/user/{id}',
})
function getUser(request, h) {
  const id = request.params.id;
  return `Hi, user ${id}!`;
}

在这个例子中,我们定义了一个方法 getUser,它使用了 @route 装饰器表示这是一个路由,并且定义了请求方法为 GET,请求路径为 /user/{id}。当接收到 /user/1 的请求时,会触发 getUser 方法并返回 Hi, user 1!

路由拦截器

在路由被处理之前或之后,我们可能需要执行一些任务。这些任务可以通过在路由上注册预处理器和后处理器来实现。在 Hapi 中,我们可以定义一个或多个预处理器和后处理器。例如:

server.route({
  method: 'POST',
  path: '/user',
  handler: (request, h) => {
      const data = request.payload;
      const name = data.name;
      const age = data.age;
      return `Hi, my name is ${name}. I am ${age} years old.`;
  },
  config: {
      pre: [
          {
              method: logRequest,
              assign: 'log'
          }
      ],
      post: [
          {
              method: logResponse,
              assign: 'log'
          }
      ]
  }
});

function logRequest(request, h) {
  console.log('Received request:', request.payload);
  return h.continue;
}

function logResponse(request, h) {
  console.log('Sending response:', request.response.source);
  return h.continue;
}

在这个例子中,我们定义了两个拦截器:logRequestlogResponse。当接收到 POST /user 的请求时,首先触发 logRequest 方法,它将请求数据打印到控制台。接着处理请求,并最终触发 logResponse 方法,它将响应数据打印到控制台。

控制器

控制器是处理业务逻辑的组件,通常与路由分离,可以让代码更加模块化、易于测试和维护。在 Hapi 中,我们可以将处理函数定义为控制器。

下面是一个简单的控制器示例:

class UserController {
  async getUser(request, h) {
    const id = request.params.id;
    const user = await getUserById(id);
    return user;
  }
}

server.route({
  method: 'GET',
  path: '/user/{id}',
  handler: UserController.getUser
});

在这个例子中,我们定义了一个 UserController 控制器,其中定义了一个 getUser 方法,它将根据传入的 id 查询用户信息并返回。我们在路由上使用 UserController.getUser 方法来处理 /user/{id} 的 GET 请求。

使用控制器有助于管理和扩展路由和业务逻辑处理代码,使代码结构更加清晰和模块化。

总结

Hapi 提供了很多先进的功能来管理路由、处理程序和中间件。本文详细介绍了 Hapi 的路由和控制器的使用,包括路由参数、路由装饰器、路由拦截器和控制器等。

通过正确使用路由和控制器,可以构建出更加健壮、可扩展和易于维护的应用程序。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65a215a1add4f0e0ffa26d0c


纠错反馈