在游戏开发中,后台系统是一个至关重要的组成部分。它负责管理游戏数据、用户信息、支付、安全等方面的工作。使用 Hapi 框架可以快速构建通用的游戏后台系统,本文将介绍 Hapi 的使用方法和实战经验。
Hapi 简介
Hapi 是一个 Node.js 的 Web 框架,它的主要特点是模块化、可扩展性强、易于测试等。Hapi 的设计理念是将路由、验证、缓存、错误处理等功能封装成插件,使得开发者可以快速构建出符合自己需求的 Web 应用程序。
Hapi 的安装和使用
Hapi 的安装非常简单,只需在终端中输入以下命令即可:
npm install hapi
安装完成后,我们可以创建一个简单的 Hapi 应用程序:
// www.javascriptcn.com code example
const Hapi = require('hapi');
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello World!';
}
});
async function start() {
await server.start();
console.log(`Server running at: ${server.info.uri}`);
}
start();在上面的代码中,我们创建了一个 Hapi 服务器,监听本地的 3000 端口,并添加了一个路由,当访问根路径时,返回 "Hello World!" 的字符串。
Hapi 的插件机制
Hapi 的插件机制是其最大的特点之一。通过插件机制,我们可以将常用的功能封装成插件,然后在应用程序中进行复用。Hapi 内置了很多插件,比如 hapi-auth-jwt2、hapi-redis、hapi-swagger 等等。
下面我们以 hapi-auth-jwt2 插件为例,介绍 Hapi 的插件机制。
// www.javascriptcn.com code example
const Hapi = require('hapi');
const jwt = require('jsonwebtoken');
const HapiJwt = require('hapi-auth-jwt2');
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
// 注册 JWT 插件
async function registerJwt() {
await server.register(HapiJwt);
server.auth.strategy('jwt', 'jwt', {
key: 'my_secret_key',
validate: (decoded, request, h) => {
// 验证 JWT 的有效性
if (decoded.username === 'admin') {
return { isValid: true };
}
return { isValid: false };
}
});
server.auth.default('jwt');
}
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'Hello World!';
},
options: {
auth: false
}
});
server.route({
method: 'POST',
path: '/login',
handler: (request, h) => {
// 登录成功,生成 JWT
const token = jwt.sign({ username: 'admin' }, 'my_secret_key');
return { token };
},
options: {
auth: false
}
});
server.route({
method: 'GET',
path: '/protected',
handler: (request, h) => {
return 'Protected!';
}
});
async function start() {
await registerJwt();
await server.start();
console.log(`Server running at: ${server.info.uri}`);
}
start();在上面的代码中,我们使用了 hapi-auth-jwt2 插件来实现 JWT 的认证功能。首先,我们通过 server.register 方法注册了 JWT 插件,并在 server.auth.strategy 方法中设置了 JWT 的验证规则。在路由中,我们使用 options.auth 属性来指定是否需要进行 JWT 认证。当访问根路径和登录接口时,不需要进行认证,访问 /protected 路径时,需要进行 JWT 认证。
Hapi 的实战经验
在使用 Hapi 进行游戏后台开发时,我们需要注意以下几点:
1. 数据库的选择
Hapi 可以支持多种不同的数据库,比如 MongoDB、MySQL、PostgreSQL 等。在选择数据库时,需要考虑到数据的读写频率、数据的结构等因素。
2. 路由的设计
路由是 Hapi 应用程序的核心,它负责处理用户请求并返回相应的结果。在设计路由时,需要考虑到路由的层级结构、路由的命名规则等因素。
3. 错误处理
在游戏后台开发中,很多异常情况都需要进行处理,比如用户输入错误、数据库连接失败等。Hapi 提供了丰富的错误处理机制,可以帮助我们更好地处理异常情况。
示例代码
// www.javascriptcn.com code example
const Hapi = require('hapi');
const jwt = require('jsonwebtoken');
const HapiJwt = require('hapi-auth-jwt2');
const Joi = require('joi');
const Boom = require('boom');
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
// 注册 JWT 插件
async function registerJwt() {
await server.register(HapiJwt);
server.auth.strategy('jwt', 'jwt', {
key: 'my_secret_key',
validate: (decoded, request, h) => {
// 验证 JWT 的有效性
if (decoded.username === 'admin') {
return { isValid: true };
}
return { isValid: false };
}
});
server.auth.default('jwt');
}
// 注册 MongoDB 插件
async function registerMongo() {
await server.register({
plugin: require('hapi-mongodb'),
options: {
url: 'mongodb://localhost:27017/mydb',
poolSize: 10,
settings: {
useNewUrlParser: true
},
decorate: true
}
});
}
// 获取 MongoDB 客户端
function getClient() {
return server.plugins['hapi-mongodb'].client;
}
// 用户注册
server.route({
method: 'POST',
path: '/register',
handler: async (request, h) => {
const { username, password } = request.payload;
const users = getClient().db().collection('users');
const user = await users.findOne({ username });
if (user) {
throw Boom.conflict('用户名已存在');
}
const result = await users.insertOne({ username, password });
return { message: '注册成功' };
},
options: {
auth: false,
validate: {
payload: Joi.object({
username: Joi.string().required(),
password: Joi.string().required()
})
}
}
});
// 用户登录
server.route({
method: 'POST',
path: '/login',
handler: async (request, h) => {
const { username, password } = request.payload;
const users = getClient().db().collection('users');
const user = await users.findOne({ username });
if (!user) {
throw Boom.unauthorized('用户名或密码错误');
}
if (user.password !== password) {
throw Boom.unauthorized('用户名或密码错误');
}
const token = jwt.sign({ username }, 'my_secret_key');
return { token };
},
options: {
auth: false,
validate: {
payload: Joi.object({
username: Joi.string().required(),
password: Joi.string().required()
})
}
}
});
// 获取用户信息
server.route({
method: 'GET',
path: '/user',
handler: async (request, h) => {
const { username } = request.auth.credentials;
const users = getClient().db().collection('users');
const user = await users.findOne({ username });
return { user };
}
});
async function start() {
await registerJwt();
await registerMongo();
await server.start();
console.log(`Server running at: ${server.info.uri}`);
}
start();在上面的代码中,我们实现了一个简单的用户注册、登录和获取用户信息的接口。使用了 hapi-auth-jwt2 插件进行 JWT 认证,使用了 hapi-mongodb 插件进行 MongoDB 数据库的操作。在路由中使用了 Joi 进行参数校验,使用了 Boom 进行错误处理。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d3ce9aa941bf71347301ff