当前位置: 首页 > Web前端 > JavaScript

nodejs+koa+Sequelize+pkg后端服务实践

时间:2023-03-26 21:09:23 JavaScript

nodejs+koa+Sequelize实践Node.js?是一个开源、跨平台的JavaScript运行环境。Koa是一个新的Web框架,由Express背后的同一个人构建,旨在成为Web应用程序和API开发领域中更小、更具表现力和更健壮的基石。通过利用异步函数,Koa可以帮助您放弃回调并大大增强错误处理。Koa没有捆绑任何中间件,而是提供了一套优雅的方法来帮助您快速愉快地编写服务器端应用程序。Sequelize是一个基于promise的Node.jsORM,目前支持Postgres、MySQL、MariaDB、SQLite和MicrosoftSQLServer。具有强大的事务支持、关系、预读和延迟加载、读复制等功能。pkg可以将Node.js项目打包为可执行文件,甚至可以在没有安装Node.js的设备上运行。基础架构模型层:数据持久化、数据处理、持久化操作接口控制层:业务模块流程控制、调用服务层接口服务层:业务操作实现类、调用模型层接口**中间件:中间件功能特性koa-static静态资源pathkoa-logger日志管理中间件koa2-cors跨域处理koa-jwt主要提供道路访问控制的功能,它会检查需要限制的资源请求koa-body是一个可以帮助中间件解析body的工具http的一部分,包括json、form、text、file等。SequelizeSequelize是一个基于promise的Node.jsORM,目前支持Postgres、MySQL、MariaDB、SQLite和MicrosoftSQLServer。具有强大的事务支持、关系、预读和延迟加载、读复制等功能。koa-routerkoa的一个路由中间件,可以将请求的URL和方法(如:GET、POST、PUT、DELETE等)匹配到对应的responder或page数据库相关的数据库配置constconfig={database:"data_base",//数据库名username:"root",//用户名password:"xxxx",//密码host:"8.16.23.x",//主机地址port:"3306",//端口号dialect:"mysql",//数据库类型,support:'mysql','sqlite','postgres','mssql'//logging:true,//是否开启logging}databaselinkconstconfig=require('./dbconfig')//引入数据库配置信息const{Sequelize,DataTypes,Op}=require("sequelize")//引入sequelize依赖constsequelize=newSequelize(config.database,config.username,config.password,{dialect:config.dialect,dialectOptions:{dateStrings:true,typeCast:true},host:config.host,port:config.port,logging:config.logging,pool:{//连接池配置min:0,//最小值numberofconnectionsmax:5,//最大链接数idle:30000,acquire:60000,},define:{//字段之间用下划线(_)分隔(默认为驼峰命名风格)underscored:true},时间one:'+08:00'})3.定义表结构const{sequelize,DataTypes}=require("../config/connect")constalliances=sequelize.define("aw_table",{id:{type:DataTypes.INTEGER(11),allowNull:false,//是否允许为空autoIncrement:true,primaryKey:true,//是否为主键},title:{type:DataTypes.STRING,allowNull:false,comment:'Name'},},{timestamps:true,//不想要createdAtcreatedAt:'create_time',//想要updatedAt但希望名字是updateTimestampupdatedAt:'update_time'})//alliances.sync({force:true})//是否自动创建表服务层1,业务操作实现类,调用模型层接口const{daoModel}=require("../model/index");classService{asyncgetList(params){const{pagenum=1,pagesize=10}=params;returndaoModel.findAndCountAll({limit:parseInt(pagesize),//跳过的实例数offset:(pagenum-1)*parseInt(pagesize),});}asyncgetDetail(id){返回daoModel.findOne({其中:{id:id,},});}}module.exports=newService();controllayer1,控制层:业务模块流程控制,调用服务层接口询问;const{count,rows}=awaitService.getList(params);if(count>0){常量列表=[];for(leti=0;i{constmatchArr=ctx.url.split("/");constid=matchArr[matchArr.length-1];//拦截文章详情IDconstresult=awaitService.getDetail(id);if(result){ctx.body={status:200,msg:"获取成功",data:{detail:result.dataValues,},};}},};接口路由1、服务模块化constRouter=require('koa-router')constrouter=newRouter()constController=require('../../controllers/admin/fileController')constrouters=router.post('/alliance',Controller.add).get('/alliance',Controller.getList).get('/alliance/:id',Controller.getDetail).delete('/alliance/:id',Controller.delete).put('/alliance/:id',Controller.update)module.exports=routers2,服务路由存储constRouter=require('koa-router')constrouter=newRouter()constRoutes=require('./路线')骗局stupload=require('./upload')constarticle=require('./article')router.use(article.routes(),article.allowedMethods())router.use(article.routes(),文章。allowedMethods())module.exports=路由器权限处理const{varifyToken}=require('../utils/utils')constRolesService=require('../services/admin/role/rolesService')module.exports=function(){returnasync(ctx,next)=>{consturl=ctx.path//释放前端显示、登录、注册等路由if(url.substring(0,11)==='/api/v1/web'||url==='/api/v1/admin/login'||url==='/api/v1/admin/register'||url==='/api/v1/admin/logout'){awaitnext()}else{//判断headers中是否存在授权if(ctx.headers&&ctx.headers.authorization===undefined){ctx.status=401ctx.body={status:401,msg:'无效的token,没有访问权限'}}else{try{//如果存在,验证token是否等于当前登录用户的用户名,如果是,则判断用户角色表中的权限字段//是是否有ctx.url,如果有则next(),否则未授权//在else中进一步判断是否可以访问接口权限{verifytoken,判断用户是否有权限访问该接口路径}consttoken=ctx.headers.authorization//解密令牌constpayload=awaitvarifyToken(token)constuserInfo=payload.userInfo//roles:['administrator'],转换为字符串constroleName=userInfo.roles.toString()constresult=awaitRolesService.getRolePermission(roleName)constpermissionApi=[]for(leti=0;i{constindex=item.path.indexOf(':')if(index!==-1){//console.log(index)//根据:id等动态拼接api路径项.path=item.path.substring(0,index)+`${ctx.url.substring(index)}`//console.log('index:'+index+''+item.path)}//过滤器返回当前访问的api接口returnnewRegExp(item.path,'g').test(ctx.url)&&item.method.toUpperCase()===ctx.request.method.toUpperCase()})//return当前访问的api接口列表//console.log(res)if(res.length===0){ctx.status=401ctx.body={code:401,msg:'您的用户没有此访问权限!'}}else{awaitnext()}}catch(err){//捕获jwt异常信息if(err.message==='jwtexpired'){ctx.status=50014ctx.body={code:50014,msg:'tokenexpired'}}elseif(err.message==='jwtmalformed'){ctx.status=50008ctx.body={code:50008,msg:'令牌无效'}}else{ctx.status=500ctx.body={code:500,msg:err.message}}}}}}}pkg打包1、相关配置pkg[options]Options:-h,--帮助输出使用信息-v,--version输出pkg版本-t,--targets逗号分隔的目标列表(参见示例)-c,--configpackage.json或任何具有顶级配置的json文件--optionsbakev8optionsintoexecutabletorunwiththemon-o,--output输出文件名或多个文件的模板--out-path保存输出一个或多个可执行文件的路径-d,--debug在打包过程中显示更多信息[off]-b,--build不要下载预构建的基础二进制文件,构建它们--public加速并公开顶级项目的源--public-packages强制指定的包被认为是public--no-bytecode跳过字节码生成并将源文件包含为纯js-C,--compress[default=None]压缩算法=Brotli或GZip示例:–为Linux、macOS和Windows制作可执行文件$pkgindex.js–从cwd中获取package.json并遵循“bin”条目$pkg。–为特定目标机器制作可执行文件$pkg-tnode14-win-arm64index.js–为您选择的目标机器制作可执行文件$pkg-tnode12-linux,node14-linux,node14-winindex.js–Bakes'--expose-gc'和'--max-heap-size=34'到可执行文件$pkg--options"expose-gc,max-heap-size=34"index.js–考虑packageA和packageB是公开的$pkg--public-packages"packageA,packageB"index.js–考虑所有包都是公开的$pkg--public-packages"*"index.js–将'--expose-gc'烘焙成可执行文件$pkg--optionsexpose-gcindex.js–减少里面打包的数据的大小带GZip的可执行文件$pkg--compressGZipindex.js1,pkg.,表示会在指定目录下寻找package.json文件,然后寻找bin字段作为入口文件2,-t使用指定打包的目标平台和Node版本,比如-tnode12-win-x64、node12-linux-x64、node12-macos-x64,可以同时打包3个平台的可执行程序;3.--out-path用于指定输出目录地址;后面的“=dist/”是指定的目录地址,也可以这样写“--out-pathdist/”,并使用一个空格而不是"="相关配置"bin":"./app.js","pkg":{"assets":["static/**/*"],"targets":["node16"],"outputPath":"dist"}测试pkg