当前位置: 首页 > 后端技术 > Node.js

hapi入门

时间:2023-04-03 16:48:56 Node.js

最近一直在学习hapiJs。有点koa2的基础,觉得很容易,但是全英文的API和koa2的实现方式不一样。想入门hapi的新人。1.构建项目1.1首先,我们创建一个目录'hapiDemo'作为项目目录,输入命令:makdirhapiDemo。1.2打开项目目录,初始化,命令如下:cdhapiDemo,初始化:npminit,1.3项目基本配置:安装hapi:npminstall--savehapi;项目使用ES6语法安装babel:npmintall--savehapi;npmstart默认启动文件为sever.js,本项目为index.js。修改启动命令。后面还会用到一些插件,请自行安装。1.4初始化安装hapi是第一步。hapiDemo项目的基本项目结构如下:这些文件的作用分别是:config:配置文件目录,db_config:数据库配置信息,plugin_config:注册插件的相关信息controllers:controllers下是业务逻辑模型:modellayerpublic:静态文件routes:路由信息log:日志信息index.js:项目启动入口文件server.js:服务配置信息2、hapistart2.1创建启动服务配置文件server.js,输入代码:consthapi=require('hapi');//创建一个hapiservervarserver=newHapi.Server();/**************serverconfig********/letconnectionOptions={port:3333,host:'localhost'};server.connection(connectionOptions);//将需要的服务器导出到别处.module.exports=server;2.2配置好服务文件后,现在我们来启动服务,首先新建一个index.js文件:constserver=require('./server');server.start(err=>{if(err)throwerr;console.log(`服务器运行于:${server.info.uri}`);});输入节点启动命令:npmstart会显示:Serverrunningat:http://localhost:3333。OK,项目启动成功。我们在浏览器中输入url:http://localhost:3333,但是找不到路由。3处理路由3.1将路由文件放在routes文件夹中。我们将创建多个路由并在模块中创建它们。首先,修改server.js文件,添加如下代码:constroute=require('./routes');//添加服务器路由route.forEach(function(api){server.route(api);});在routes中新建一个index.js,每个新的route文件都在index.js文件中引入。module.exports=[require(__dirname+'/helloWorld.js'),require(__dirname+'/login.js'),require(__dirname+'/file.js'),require(__dirname+'/auth.js')]3.2定义路由需要三个基本元素:路径、方法和处理程序。Methods选项可以是任何有效的HTTP方法或方法数组。路径选项必须是一个字符串,尽管它可以包含命名参数。要命名路径中的参数,只需将其用{}包裹起来。处理程序选项是一个带有两个参数的函数:request和request。在路由中新建一个helloWorld.js:letindex={method:'GET',path:'/',handler:function(request,reply){reply('hello,world');}};lethello={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-...4加载插件一般在nodeJS中,我们加载一个插件,安装后使用require插件名即可,但在hapiJS中,需要通过server.register()方法导入。以下示例使用插件inert处理静态文件:server.register(require('inert'),(err)=>{if(err){console.error('Failedtoloadaplugin:',err);}});但并不是所有的插件都需要使用server.register()引入,直接使用require即可。为什么要用server.register()引用,我还是不是很清楚。在这个项目中,我把所有的插件配置放在config/plugin_config.js中:constSwaggerOptions={info:{'title':'hapiDemoAPIDocumentation','version':'0.0.1'}};constgoodOptions={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:'*'}]},{模块:'good-squeeze',name:'SafeJson'},{模块:'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')}];inserver.js:constplugins=require('./config/plugin_config');//注册所有插件plugin}});5renderstaticfilesAndView5.1在web应用中,不可避免地会在hapi中提供一个简单的文件、图片或静态html,使用惰性插件来处理静态文件。npminstall--saveinert在routes文件夹下创建file.js:letstatic={method:'GET',path:'/staticFile',handler:function(request,reply){reply.file('./public/static.html');}};module.exports=static;在public文件夹下添加static.html文件,内容可选。保存并运行。5.2hapi可以使用模板渲染,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){throwerr;//加载插件时发生了不好的事情}});加载视觉插件,它增加了对模板渲染的支持。更多配置项:https://hapijs.com/tutorials/...渲染势图,在file.js文件中添加新路由:lettemp={method:'GET',path:'/view',配置:{auth:false,handler:function(request,reply){reply.view('login');}}};module.exports=[static,temp];logincontentself-fill6在web应用中访问数据库,我们可能会写很多数据库访问层的代码,数据库的保存,删除,读取,hapi如何访问数据库?本演示以MySQL为例。不懂数据库的程序员不是好程序员,但是我早早的把数据库的一点点回馈给了老师。我选择了Node的ORM框架Sequelize来操作数据库。hapi-sequelize插件对se??quelize做了一个非常简单的封装,但是它对hapi和sequelize的版本有要求,本项目没有用到。有兴趣的可以研究一下https://github.com/danecando/...6.1在server.js中添加代码:constmodels=require('./models');//连接数据库varinitDb=function(){varsequelize=模型.续集;//判断数据库连接是否成功sequelize.sync({force:false}).then(function(){console.log("连接成功");}).catch(function(err){console.log(“由于错误导致连接失败:%s”,err);});};初始化数据库();6.2使用Sequelize操作MySQL,首先需要做两个准备工作,(1)创建一个sequelize对象实例,连接数据库,在models中添加index.js,代码如下:constfs=require("fs");constpath=require("path");constSequelize=require("sequelize");constconfig=require('../config/db_config');letdb={};//创建一个sequelize对象例如,连接到数据库letsequelize=newSequelize(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){varmodel=sequelize["import"](path.join(__dirname,file));db[model.name]=model;});db.sequelize=sequelize;db.Sequelize=续集;模块.exports=db;db_config文件是数据库的配置信息(2)定义model文件user(在本项目中,主要实现登录),告诉Sequelize如何映射数据库表。module.exports=function(sequelize,DataTypes){varUser=sequelize.define("User",{id:{type:DataTypes.INTEGER,primaryKey:true},user_no:DataTypes.STRING,old_kn_userid:DataTypes.STRING,昵称:DataTypes.STRING,password:DataTypes.STRING,},{freezeTableName:true,//Model对应的表名会和模型名一致timestamps:false});返回用户;};更多Sequelize的学习可以参考:https://itbilu.com/nodejs/npm...6.3配置完成后,我们就可以在routinghandler中使用这个实例了。新建一个login.js:constJoi=require('joi');constcontrollers=require('../controllers');letlogin2={method:'get',path:'/tologin2',config:{验证:{查询:{昵称:Joi.min(6).max(30)required(),//validation}},id:'login2'},handler:controllers.user.login2,};module.exports=login2;joi是hapijs自带的数据验证模块。高度封装了常用的验证功能。更多用法:https://github.com/hapijs/joi...。6.4接下来我们将访问数据库。(1)newindex.jsconstrequireDirectory=require('require-directory');module.exports=requireDirectory(模块);require-directory的作用是递归遍历指定目录,require()每个文件,返回一个包含这些模块嵌套的哈希结构的文件。(2)user.js:letmodels=require('../models')module.exports={login2:function(request,reply){letuserInfo=models.User.findOne({其中:{昵称:request.query.nickname}}).then(function(result){letresponseMess={};if(result!==null){responseMess={code:1,message:'已经在数据库中查询'}}else{responseMess={code:-1,message:'尚未在数据库中查询'}}reply(reponseMess);});}};简单的demo查询,用户是否已经存在7自动生成swagger文档使用hapi写api的时候,有一种感觉,代码都是文档化的,这些代码真的可以自动生成swagger文档。使用hapi插件hapi-swagger,简单配置插件,首先修改plugin_config.js文件:constSwaggerOptions={info:{'title':'hapiDemoAPIDocumentation','version':'0.0.1'}};module.exports=[{'register':require('hapi-swagger'),'options':SwaggerOptions},];然后修改/tologin2:letlogin2={method:'get',path:'/tologin2',config:{auth:false,description:'Routingwithparameters',notes:'loginapi',tags:['api'],//写这句话启用swagger生成函数validate:{query:{nickname:Joi.required(),}},id:'login2'},处理程序:controllers.user.login2,};运行,打开http://localhost:3333/documen...8测试未完成待续...