UNPKG

egg-xc-base

Version:

a base framework with egg.js

404 lines (324 loc) 11.3 kB
# egg-xc-base base framework of our egg ## QuickStart ``` egg-bin init 项目名 --type-simple 将package.json egg对象下面 里面增加一行: egg: { framework:'egg-xc-base' } 然后使用yarn add egg-xc-base初始化项目 初次初始化yarn dev 脚手架会自动生成一些配置目录和文件 然后使用 $yarn init-config 指令初始化项目配置文件 ``` ### config/plugin.js ```js module.exports = { mysql : { enable: false, package: 'egg-mysql' }, xcSSO :{ enable:false, package :'egg-xc-sso' } }; mysql插件默认是关闭状态 xcSSO鉴权默认是关闭状态 ``` ### config/config.default.js ```js config.xcSSO = {//统一认证服务配置 //客户端ID 必配 clientId : '', //客户端秘钥 必配 clientSecret : '', //上下文根 选配默认 / prefix:config.static && config.static.prefix ? config.static.prefix : '/', //回调IP端口 必配 eg: http://127.0.0.1:${config.cluster.listen.port} 备注:此处IP为服务端生成环境IP地址或者域名 callbackIpPort:`http://127.0.0.1:${config.cluster.listen.port}`, //回调路径 选配默认 /sso/callback 最终拼接规则`${config.xcSSO.callbackIpPort}${config.xcSSO.prefix}/sso/callback` callbackURL: `/sso/callback`, //统一身份认证服务器IP端口 必配 eg:http://192.168.137.1:5001 authIpPort:`http://192.168.137.1:5001`, //登录URL 选配 默认/sso/login 最终拼接规则`${config.xcSSO.callbackIpPort}${config.xcSSO.prefix}/sso/login` loginURL : `/sso/login`, //登出URL 选配默认 /sso/logout 最终拼接规则`${config.xcSSO.callbackIpPort}${config.xcSSO.prefix}/sso/logout` logoutURL : `/sso/logout`, //登录成功后回调地址 选配默认 /index.html 最终拼接规则`${config.xcSSO.callbackIpPort}${config.xcSSO.prefix}/index.html` successRedirect : `/index.html`, } config.checkLogin = {//登录拦截白名单 whiteList : [ `${config.static.prefix}${config.xcSSO.callbackURL}`, `${config.static.prefix}${config.xcSSO.loginURL}`, `${config.static.prefix}${config.xcSSO.successRedirect}`, ] } config.xcSSO: 鉴权模块的一些配置项 config.checkLogin: 框架依赖的egg-xc-sso 中间件会抓取每一个http请求(public下静态资源除外),这里可以配置白名单。脚手架默认将鉴权的对应路径加入配置 ``` ### 鉴权逻辑 ``` 1.框架默认使用OAuth2.0进行鉴权操作 OAuth 2.0 规定了四种获得令牌的流程。 1.1授权码(authorization-code) 1.2隐藏式(implicit1.3密码式(password): 1.4客户端凭证(client credentials) 本框架主要对1.1 1.3 1.4进行了封装,开发者无需关注具体是怎么和鉴权服务进行交互的,框架会自动帮你将登录接口、登出接口、刷新token业务全部自动搞定。 2.本框鉴权一般 配合xc-oauth(基于oauth2-server进行改进优化过的工程),项目进行使用使用。亦可对框架进行扩展,集成GitHub,推特,微信等第三方Oauth Server。 3.获取用户 凡是通过鉴权的接口可通过 ctx.state.user 获取用户信息 "id": 3, "username": "test01", "phone": "13666778899", "email": "test01@dalitek.com", "create_at": "1608521057872", "update_at": "1608521057872", "last_sign_in_at": "1609411919009" 愉快的使用就可以了 4.前端登录 、登出 4.1登录 config.xcSSO.loginURL 配置里的URL让前端直接调用即可 GET、DELETE、POST、PUT请求都可以 4.2 config.xcSSO.logoutURL 配置里的URL让前端直接调用即可 GET、DELETE、POST、PUT请求都可以 5.客户端登录、登出、刷新token 直接使用xc-oauth提供的用户、密码鉴权模式即可。 然后所有业务请求Header中加入Authorization = Bearer accessToken 即可 框架会自动适配,来源于客户端的Header还是浏览器的Cookie 6.登出来源客户端、浏览器识别 框架会自动判别请求来源进行登出、浏览器无需加入任何header、客户端加入Authorization = Bearer accessToken 即可 7.开给第三方的API,鉴权认证 让他们参考xc-oauth 提供的客户端凭证 鉴权方式即可,他们所有的请求header里面加入Authorization = Bearer accessToken 即可 上述业务逻辑与自研应用一致 8.第三方单点登录 让他们参考xc-oauth 提供的授权码 鉴权方式即可,框架和xc-oauth自动完成单点登录 ``` ### 框架相对于xc.base ``` 1.去掉了egg-xc-auth插件,使用更完善的 egg-xc-sso进行鉴权 2.脚手架自动生成的代码,上下文根采用 config.default中配置的,包括./init/.init.json , router.js , controller.js 3.脚手架自动生成的代码去掉冗余注释,apidoc看起来更清爽了 4.plugin默认禁用了mysql插件、xc-SSO插件,初始化项目的时候更加友好,不报错且不用加额外配置 5.命名规范了下,方便debug的时候查找了,再也不用拉到node_module最底下查找了 ``` ## 命令行工具 ### 1. 生成模块 ``` 指令:yarn api-init 模块 模块名称 [表名称] [数据库] 1.模块 2.模块名称 3.[表名称]可选 如果不传,初始化空的controller.js和service.js 4.[数据库]可选 默认db1 eg: yarn api-init room 房间 jg_room db1 ``` ### 2. 生成模块下的上下文 ``` 指令:yarn api-ctx 模块 上下文根 [表名称] [数据库] 1.模块 2.上下文根 3.[表名称]可选 如果不传,初始化空的controller.js和service.js 4.[数据库]可选 默认db1 eg: yarn api-init room 房间 jg_room db1 ``` ### 3. 生成api ``` 指令:yarn api 模块 上下文根 方法名 1.模块 2.上下文根 3.方法名 eg: yarn api room room getByBimId 1) 在 api/模块/.init/.init.json中,ctxs下面的上下文根对象的apis (eg: [/api/room/.init/.init.json].ctxs.room.apis )数组添加 { "fun": "getByBimId", "method": "DELETE", "url": "/bimc/v1.0.0/room/getByBimId/:bim_id", "name": "根据bimid查询房间" } 2) 运行指令 ``` ### 4. 生成api/ apidoc文档 *默认在app/public/doc/api/下生成静态资源* ``` 指令:yarn doc-api ``` ### 5. 生成app/ apidoc文档 *默认在app/public/doc/app/下生成静态资源* ``` 指令:yarn doc-app ``` ### 6. 生成config/config.default.js 及 config/plugin.js 模板文件(可选) *注:该命令会覆盖当前 config/config.default.js 及 config/plugin.js* *建议用于项目初始化* ``` 指令:yarn init-config ##API ###BaseController ```js //简化helper获取方式由this.ctx.helper 简化为this.helper get helper() // 错误统一处理 status 为200 http返回 // { // code: 500, // message: err.message, // } error(err) //content为错误内容可为object status为200 http返回 // { // code: 500, // message: err.message, // content // } errorContent(err, content) // 成功统一处理 如果data为null则统一处理为执行失败错误 // { // code: 0, // message: 'success', // content: data, // } success(data) //统一成功和失败错误处理 //如果asycnfunction 抛出错误则执行失败处理 async result(asyncFunction) //统一处理 http参数验证及错误处理 //info验证泛型,body为验证目标对象 //body如果为undefined 默认验证request.body //如果验证成功返回 true //如果验证失败返回 false 并统一按照errorContent处理错误 validate(info, body) ``` ### DbController DbService DbController 继承自BaseController ```js //获取helper里面的数据库对象 简化db的获取为this.db get db() //直接执行sql语句 框架统一处理错误,无错误抛出 async doQuery(_sql) //直接用db1执行sql 如果查不到就返回null,查到直接返回对象 async doQueryObj(_sql) //直接执行sql语句 有错误抛出 async doQueryError(_sql) //执行事务 async tran(asyncFunction) //事务回调里面直接执行sql语句 async doQueryConn(conn,_sql) //事务回调里面直接执行sql语句 如果查不到就返回null,查到直接返回对象 async doQueryConnObj(conn,_sql) //多数据源执行sql语句 async doMQuery(dbId,_sql) //多数据源执行事务 async tranM(dbId,asyncFunction) //统一防sql注入处理,sql语句里面的参数用this.to()包裹 to(params) ``` ### helper ```js //数据库操作相关 已集成到DbService和DbController 如果需要自行实现见源码 helper.db //时间操作相关 helper.time // 获取当前时间格式 YYYY-MM-DD HH:mm:ss.SSS helper.time.getCurrentTime() ``` ### report中间件 reportEnd中间件 统一为http请求加上唯一requestId 追加到 httpQuery 统一打印 http请求入参 统一打印 http执行耗时及结束标志 ### config ```js // mysql 数据库配置 const mysqlCon = { clients: { // clientId, 获取client实例,需要通过 app.mysql.get('clientId') 获取 db1: { // 数据库名默认 database: 'xc_main', }, db2: { // 数据库名 database: 'xc_app', }, // ... }, // 所有数据库配置的默认值 default: { // host host: '', // 端口号 port: '', // 用户名 user: '', // 密码 password: '', }, // 是否加载到 app 上,默认开启 app: true, // 是否加载到 agent 上,默认关闭 agent: false, }; ``` ## Example ### BaseController ```js 'use strict'; const Controller = require('xc.base').BaseController; class TemplateController extends Controller { async create() { if (!this.validate({ name: { type: 'string' }, userid: { type: 'string' }, })) return; const { ctx, service } = this; //注意 result 里面没有 await await this.result(service.template.create(ctx.request.body)); } async list() { await this.success(await this.service.template.list()); } } module.exports = TemplateController; ``` ### DbService ```js 'use strict'; const Service = require('xc.base').DbService; class TemplateService extends Service { async create(info) { return await this.doQueryError( `insert into xc_p_template(name,createtime,updatetime,createuser,updateuser) values( ${this.to(info.name)},${this.to(this.helper.time.getCurrentTime())},${this.to(this.helper.time.getCurrentTime())} ,${this.to(info.userid)},${this.to(info.userid)})` ); } async list() { return await this.doQuery('select * from xc_p_template'); } async getSowingsTran(dateTime) { return await this.tran( async conn => { const _sql1 = `update xc_config_sowing set title = ${this.to(dateTime)} where id = 39`; await this.doQueryConn(conn, this_sql1); const _sql2 = 'select * from xc_config_sowing where id = 39'; const result = await this.doQueryConn(conn, _sql2); this.logger.info(`dateTime=${dateTime}`); this.logger.info(`result=${JSON.stringify(result)}`); return result; }); } } module.exports = TemplateService; ``` ### config ```js //覆盖写出字段名 保留未写出字段 exports.mysql = { clients: { db1: { database: 'aaa', }, }, }; ```