摘要:最近一直在学习,有点的基础以为会容易呢,但是全英文的,不同于的实现方式,看起来大写的懵啊,整理此文,希望能够帮助到一些想要入门的新人。,项目启动成功。若要在路径中命名参数,只需用将其包装。
最近一直在学习hapiJs,有点koa2的基础以为会容易呢,但是全英文的API,不同于koa2的实现方式,看起来大写的懵啊,整理此文,希望能够帮助到一些想要入门hapi的新人。
1、搭建项目1.1 首先我们创建一个目录‘hapiDemo’作为项目目录,输入命令:
makdir hapiDemo。
1.2 打开项目目录,初始化,命令如下:
cd hapiDemo, 初始化:npm init,
1.3 项目基础配置:
安装hapi: npm install --save hapi;
项目使用了ES6语法安装babel: npm intall --save hapi;
npm start默认是的启动文件是sever.js,本项目是index.js,修改启动命令,
下文中还是用了一些插件,请自行安装。
1.4 初始化并安装hapi是第一步,hapiDemo 项目的基础项目结构如下图:
这些文件的作用是:
config:配置文件目录,db_config:数据库的配置信息,plugin_config:注册插件的相关信息
controllers:controllers下是业务逻辑
models:model 层
public:静态文件
routes:路由信息
log:日志信息
index.js:项目启动入口文件
server.js:服务配置信息
2、hapi start2.1 创建启动服务配置文件server.js,输入一下代码:
const Hapi = require("hapi"); //Create a hapi server var server = new Hapi.Server(); /**************server config********/ let connectionOptions={ port: 3333, host: "localhost" }; server.connection(connectionOptions); // Export the server to be required elsewhere. module.exports = server;
2.2 配置完服务文件,现在我们来启动服务,先新建一个index.js文件:
const server=require("./server"); server.start(err=>{ if(err) throw err; console.log( `Server running at: ${server.info.uri}`); }); 输入node启动命令:npm start 将会显示:Server running at: http://localhost:3333。OK,项目启动成功。 我们在浏览器中输入url:http://localhost:3333,
找不到路由。
3.1 将路由文件放在routes文件夹里,我们将创建多个路由,分模块创建,首先修改server.js文件,新增如下代码:
const route=require("./routes"); // Add the server routes route.forEach(function(api){ server.route(api); });
在routes新建index.js,每新增一个路由文件,在index.js文件中引入。
module.exports=[ require(__dirname+"/helloWorld.js"), require(__dirname+"/login.js"), require(__dirname+"/file.js"), require(__dirname+"/auth.js") ]
3.2 定义路由需要三个基础元素:path,method,handler。Methods的选项可以是任何有效的HTTP方法,也可以是方法数组。path选项必须是字符串,尽管它可以包含命名参数。若要在路径中命名参数,只需用{ }将其包装。handler选项是一个函数,它接受两个参数:request和request。
在routes里新建一个helloWorld.js:
let index={ method: "GET", path: "/", handler: function(request, reply){ reply("hello,world"); } }; let hello={ method: ["GET", "POST"], path: "/hello/{user?}", handler: function (request, reply) { reply("Hello " + encodeURIComponent(request.params.user) + "!"); } }; module.exports=[index,hello];
保存重启服务,在浏览器中访问,显示如下:
更多用法请查看api:https://hapijs.com/api#route-...
一般在nodeJS中,我们加载一个插件,安装后使用require 插件名称就OK了,但是在hapiJS中,需要通过server.register()方法引入。
以下文中使用处理静态文件的插件 inert 举例:
server.register(require("inert"), (err) => { if (err) { console.error("Failed to load a plugin:", err); } });
但不是所有的插件都需要使用server.register()引入,直接使用require即可。
为什么使用server.register()引用,我至今不是很清楚。
在本项目中,我把所有的插架配置放在了config/plugin_config.js中:
const SwaggerOptions = { info: { "title": "hapiDemo API Documentation", "version": "0.0.1" } }; const goodOptions = { ops: { interval: 1000 }, reporters: { myConsoleReporter: [{ module: "good-squeeze", name: "Squeeze", args: [{ log: "*", response: "*" }] }, { module: "good-console" }, "stdout"], myFileReporter: [{ module: "good-squeeze", name: "Squeeze", args: [{ log: "*", response: "*" ,request:"*"}] }, { module: "good-squeeze", name: "SafeJson" }, { module: "good-file", args: ["./log/fixtures/awesome_log"] }], myHTTPReporter: [{ module: "good-squeeze", name: "Squeeze", args: [{ error: "*" }] }, { module: "good-http", args: ["http://prod.logs:3000", { wreck: { headers: { "x-api-key": 12345 } } }] }] } }; module.exports = [ { register:require("good"), goodOptions, }, { register:require("hapi-auth-jwt2") }, { register:require("inert") }, { register:require("hapi-auth-basic") }, { register:require("./../auth") }, { "register": require("hapi-swagger"), "options": SwaggerOptions }, { register:require("vision") } ];
在server.js中:
const plugins=require("./config/plugin_config"); //Register all plugins server.register(plugins, function (err) { if (err) { throw err; // something bad happened loading a plugin } });5 渲染静态文件和视图
5.1 在Web应用程序中,不可避免地,需要提供一个简单的文件,图片或者静态html。在hapi 中使用 inert 插件来处理静态文件。
npm install --save inert
在routes文件夹中创建一个file.js:
let static={ method: "GET", path: "/staticFile", handler: function (request, reply) { reply.file("./public/static.html"); } }; module.exports=static;
在public文件夹下新增一个static.html的文件,内容随意。保存然后运行。
5.2 hapi 可以使用模板渲染,hapi默认使用的是handlebars,要开始视图,首先我们必须在服务器上配置至少一个模板引擎。这是通过使用server.views方法做的,修改server.js文件:
server.register(plugins, function (err) { server.views({ engines: { "html": { module: require("handlebars") } }, relativeTo:__dirname, path:"public/templates" }); if (err) { throw err; // something bad happened loading a plugin } });
加载 vision 插件,它增加了模板渲染支持哈啤。
更多配置项:https://hapijs.com/tutorials/...
渲染势图,在file.js文件中新增路由:
let temp={ method: "GET", path: "/view", config: { auth: false, handler: function (request, reply) { reply.view("login"); } } }; module.exports=[static,temp];
login的内容自行填充
6 访问数据库在web应用程序中,我们可能写特别多数据库访问层的代码,数据库保存,删除,读取,那hapi如何访问数据库呢?本demo以MySQL为例。
不懂数据库的程序员不是好程序员,但是我早早就把数据库的一点皮毛还给了老师,我选择Node的ORM框架Sequelize来操作数据库。
hapi-sequelize插件对sequelize做了很简单的封装,但是它对Hapi和sequelize的版本有要求,在本项目中没有使用,有兴趣的的可以研究 https://github.com/danecando/...
6.1 在server.js添加代码:
const models=require("./models"); //Connect database var initDb = function(){ var sequelize = models.sequelize; //Determine if the database connection is successful sequelize.sync({force: false}).then(function() { console.log("connection successed"); }).catch(function(err){ console.log("connection failed due to error: %s", err); }); }; initDb();
6.2 使用Sequelize操作MySQL需要先做两件准备工作,
(1)创建一个sequelize对象实例,连接数据库,在models新增index.js,代码如下:
const fs = require("fs"); const path = require("path"); const Sequelize = require("sequelize"); const config = require("../config/db_config"); let db = {}; //创建一个sequelize对象实例,连接数据库 let sequelize = new Sequelize(config.database, config.username, config.password,{ host: config.host, dialect: "mysql", pool: { max: 5, min: 0, idle: 30000 } }); fs .readdirSync(__dirname) .filter(function(file) { return (file.indexOf(".") !== 0) && (file !== "index.js"); }) .forEach(function(file) { var model = sequelize["import"](path.join(__dirname, file)); db[model.name] = model; }); db.sequelize = sequelize; db.Sequelize = Sequelize; module.exports = db;
db_config文件是数据库的配置信息。
(2)定义模型文件user(在本项目中主要是实现登陆),告诉Sequelize如何映射数据库表。
module.exports = function(sequelize, DataTypes) { var User = sequelize.define("User", { id:{ type: DataTypes.INTEGER, primaryKey: true }, user_no:DataTypes.STRING, old_kn_userid:DataTypes.STRING, nickname:DataTypes.STRING, password:DataTypes.STRING, }, { freezeTableName: true, // Model 对应的表名将与model名相同 timestamps: false }); return User; };
更多Sequelize的学习可以参考:https://itbilu.com/nodejs/npm...
6.3 经过配置后,接下来我们可以在路由handler中使用这个实例啦。
新建一个login.js:
const Joi=require("joi"); const controllers=require("../controllers"); let login2={ method: "get", path: "/tologin2", config: { validate:{ query: { nickname:Joi.min(6).max(30)required(),//校验 } }, id: "login2" }, handler: controllers.user.login2, }; module.exports=login2;
joi 是 hapijs 自带的数据校验模块,他已经高度封装常用的校验功能,更多用法:https://github.com/hapijs/joi...。
6.4 接下来我们就要访问数据库啦。
(1)新建index.js
const requireDirectory = require("require-directory"); module.exports = requireDirectory(module);
require-directory的作用是递归遍历指定目录,require()每个文件,并返回一个包含这些模块嵌套的hash结构。
(2)user.js:
let models=require("../models") module.exports={ login2:function(request,reply){ let userInfo=models.User.findOne({ where:{ nickname: request.query.nickname } }).then(function(result){ let reponseMess={}; if(result!==null){ reponseMess={ code:1, message:"已经在数据库中查询到" } }else{ reponseMess={ code:-1, message:"未已经在数据库中查询到" } } reply(reponseMess); }); } };
简单的demo查询,用户是否已存在
7 自动生成swagger文档使用hapi写api时,有种代码既文档的感觉,而且这些代码也真的可以自动生成swagger文档。
使用hapi插件hapi-swagger,简单配置下插件,先修改下plugin_config.js文件:
const SwaggerOptions = { info: { "title": "hapiDemo API Documentation", "version": "0.0.1" } }; module.exports = [ { "register": require("hapi-swagger"), "options": SwaggerOptions }, ];
然后修改/tologin2:
let login2={ method: "get", path: "/tologin2", config: { auth:false, description: "Routing with parameters", notes: "login api", tags: ["api"],//写上这句,开启生成swagger功能 validate:{ query: { nickname:Joi.required(), } }, id: "login2" }, handler: controllers.user.login2, };
运行,打开 http://localhost:3333/documen...
8 测试未完待续……
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/87111.html
摘要:里面的验证是基于和这两个概念的。另一方面,是一个预先配置的命名的实例。注册了一个插件该插件创建了一个命名为的。执行上述文件,访问。在弹出的登录框中输入用户名及密码,页面将展示如果报错,可使用模块替代,其余代码无需改变。 hapi里面的Authentication(验证)是基于scheme和strategies这两个概念的。你可以把scheme理解为一个通用型的验证,是那种基础的,概要的...
摘要:框架,用官网的简介来说就是是构建应用程序和服务的丰富框架,它使开发人员能够专注于编写可重用的应用程序逻辑,而不是花时间构建基础设施。用自己的话简单来说,就是个类似,之类的服务基础框架。同时全局环境直接获取。 showImg(https://segmentfault.com/img/bVbrV3m?w=572&h=350); hapi框架,用官网的简介来说就是:Hapi是构建应用程序和...
摘要:框架,用官网的简介来说就是是构建应用程序和服务的丰富框架,它使开发人员能够专注于编写可重用的应用程序逻辑,而不是花时间构建基础设施。用自己的话简单来说,就是个类似,之类的服务基础框架。 showImg(https://segmentfault.com/img/bVbrV3m?w=572&h=350); hapi框架,用官网的简介来说就是:Hapi是构建应用程序和服务的丰富框架,它使开...
阅读 2164·2021-11-11 16:55
阅读 1684·2019-08-30 15:54
阅读 2816·2019-08-30 15:53
阅读 2210·2019-08-30 15:44
阅读 1151·2019-08-30 15:43
阅读 964·2019-08-30 11:22
阅读 1941·2019-08-29 17:20
阅读 1566·2019-08-29 16:56