服务器方法 #
一、方法概述 #
1.1 什么是服务器方法? #
服务器方法是附加到服务器实例上的函数,可以在整个应用中共享和复用。
1.2 基本定义 #
javascript
server.method('formatDate', (date) => {
return new Date(date).toISOString();
});
server.route({
method: 'GET',
path: '/date',
handler: (request, h) => {
return server.methods.formatDate(new Date());
}
});
二、定义方法 #
2.1 简单方法 #
javascript
server.method('greet', (name) => {
return `Hello, ${name}!`;
});
server.route({
method: 'GET',
path: '/greet/{name}',
handler: (request, h) => {
return server.methods.greet(request.params.name);
}
});
2.2 异步方法 #
javascript
server.method('getUser', async (id) => {
const user = await User.findById(id);
return user;
});
server.route({
method: 'GET',
path: '/users/{id}',
handler: async (request, h) => {
return await server.methods.getUser(request.params.id);
}
});
2.3 带选项的方法 #
javascript
server.method({
name: 'calculate',
method: (a, b, operation = 'add') => {
switch (operation) {
case 'add': return a + b;
case 'subtract': return a - b;
case 'multiply': return a * b;
case 'divide': return a / b;
default: throw new Error('Unknown operation');
}
}
});
三、方法缓存 #
3.1 启用缓存 #
javascript
server.method('getUser', async (id) => {
console.log('Fetching user from database');
return await User.findById(id);
}, {
cache: {
expiresIn: 60 * 1000,
generateTimeout: 100
}
});
3.2 缓存配置选项 #
javascript
server.method('getProduct', async (id) => {
return await Product.findById(id);
}, {
cache: {
cache: 'redis-cache',
expiresIn: 60 * 60 * 1000,
staleIn: 30 * 60 * 1000,
staleTimeout: 100,
generateTimeout: 1000
}
});
3.3 缓存键生成 #
javascript
server.method('search', async (query, filters) => {
return await SearchService.search(query, filters);
}, {
cache: {
expiresIn: 60 * 1000,
generateTimeout: 100
},
generateKey: (query, filters) => {
return `${query}:${JSON.stringify(filters)}`;
}
});
四、方法命名空间 #
4.1 命名空间方法 #
javascript
server.method('user.getById', async (id) => {
return await User.findById(id);
});
server.method('user.getByEmail', async (email) => {
return await User.findByEmail(email);
});
server.method('user.create', async (data) => {
return await User.create(data);
});
4.2 使用命名空间方法 #
javascript
server.route({
method: 'GET',
path: '/users/{id}',
handler: async (request, h) => {
return await server.methods.user.getById(request.params.id);
}
});
五、方法绑定 #
5.1 绑定上下文 #
javascript
server.method('format', function (value) {
return `${this.prefix}${value}${this.suffix}`;
}, {
bind: {
prefix: '[',
suffix: ']'
}
});
六、完整方法配置 #
6.1 配置对象 #
javascript
server.method({
name: 'userService.getProfile',
method: async function (userId) {
const user = await this.User.findById(userId);
const posts = await this.Post.findByUserId(userId);
return { user, posts };
},
options: {
bind: {
User: UserModel,
Post: PostModel
},
cache: {
expiresIn: 60 * 1000,
generateTimeout: 100
},
generateKey: (userId) => `profile:${userId}`
}
});
七、批量定义 #
7.1 定义多个方法 #
javascript
server.method([
{
name: 'math.add',
method: (a, b) => a + b
},
{
name: 'math.subtract',
method: (a, b) => a - b
},
{
name: 'math.multiply',
method: (a, b) => a * b
},
{
name: 'math.divide',
method: (a, b) => a / b
}
]);
八、实际应用 #
8.1 数据库查询 #
javascript
server.method('db.findUser', async (id) => {
const result = await server.app.db.query(
'SELECT * FROM users WHERE id = $1',
[id]
);
return result.rows[0];
}, {
cache: {
expiresIn: 60 * 1000,
generateTimeout: 100
}
});
8.2 外部API调用 #
javascript
const Wreck = require('@hapi/wreck');
server.method('api.getWeather', async (city) => {
const { payload } = await Wreck.get(
`https://api.weather.com/${city}`
);
return JSON.parse(payload);
}, {
cache: {
expiresIn: 10 * 60 * 1000,
generateTimeout: 5000
}
});
8.3 计算密集型任务 #
javascript
server.method('calculateStats', (data) => {
let sum = 0;
for (let i = 0; i < data.length; i++) {
sum += data[i];
}
return {
sum,
avg: sum / data.length,
count: data.length
};
}, {
cache: {
expiresIn: 60 * 60 * 1000,
generateTimeout: 10000
},
generateKey: (data) => {
return `stats:${data.length}:${data[0]}:${data[data.length - 1]}`;
}
});
九、缓存策略 #
9.1 配置缓存 #
javascript
const server = Hapi.server({
port: 3000,
cache: [
{
name: 'memory-cache',
provider: {
constructor: require('@hapi/catbox-memory'),
options: {
maxByteSize: 100 * 1024 * 1024
}
}
},
{
name: 'redis-cache',
provider: {
constructor: require('@hapi/catbox-redis'),
options: {
partition: 'my-app',
host: 'localhost',
port: 6379
}
}
}
]
});
9.2 使用指定缓存 #
javascript
server.method('getHotData', async (key) => {
return await fetchHotData(key);
}, {
cache: {
cache: 'memory-cache',
expiresIn: 30 * 1000
}
});
server.method('getColdData', async (key) => {
return await fetchColdData(key);
}, {
cache: {
cache: 'redis-cache',
expiresIn: 24 * 60 * 60 * 1000
}
});
十、缓存失效 #
10.1 手动清除缓存 #
javascript
server.route({
method: 'PUT',
path: '/users/{id}',
handler: async (request, h) => {
const user = await User.update(request.params.id, request.payload);
await server.methods.getUser.cache.drop(request.params.id);
return user;
}
});
10.2 自动更新 #
javascript
server.method('getSettings', async () => {
return await Settings.findAll();
}, {
cache: {
expiresIn: 60 * 1000,
staleIn: 30 * 1000,
staleTimeout: 100,
generateTimeout: 1000
}
});
十一、完整示例 #
11.1 用户服务 #
javascript
const Hapi = require('@hapi/hapi');
const CatboxRedis = require('@hapi/catbox-redis');
const init = async () => {
const server = Hapi.server({
port: 3000,
cache: [{
name: 'redis',
provider: {
constructor: CatboxRedis,
options: {
partition: 'my-app',
host: 'localhost',
port: 6379
}
}
}]
});
server.method('user.getById', async (id) => {
console.log('Fetching user from database');
return await User.findById(id);
}, {
cache: {
cache: 'redis',
expiresIn: 60 * 60 * 1000,
generateTimeout: 100
},
generateKey: (id) => `user:${id}`
});
server.method('user.getByEmail', async (email) => {
return await User.findByEmail(email);
}, {
cache: {
cache: 'redis',
expiresIn: 60 * 60 * 1000,
generateTimeout: 100
}
});
server.method('user.create', async (data) => {
const user = await User.create(data);
return user;
});
server.route([
{
method: 'GET',
path: '/users/{id}',
handler: async (request, h) => {
return await server.methods.user.getById(request.params.id);
}
},
{
method: 'POST',
path: '/users',
handler: async (request, h) => {
const user = await server.methods.user.create(request.payload);
return h.response(user).code(201);
}
}
]);
await server.start();
console.log('Server running on %s', server.info.uri);
};
init();
十二、总结 #
服务器方法要点:
| 功能 | 说明 |
|---|---|
| server.method() | 定义方法 |
| cache | 方法缓存 |
| generateKey | 缓存键生成 |
| bind | 绑定上下文 |
| 命名空间 | 方法分组 |
下一步,让我们学习缓存策略!
最后更新:2026-03-28