zoukankan      html  css  js  c++  java
  • node.js 接口调用示例

    测试用例git地址(node.js部分):https://github.com/wuyongxian20/node-api.git

    项目架构如下:

    controllers:

      文件夹下为接口文件

    logs:

      log4js 日志打印文件

    mongodb:

      mongodb数据库配置及帮助类的封装

    mysql:

      mysql数据库配置及数据库的封装

    utils:

      帮助类

    app.js:

      node.js启动文件

    controller.js:

      controller接口封装调用

    相互关系:

    >package.json 项目依赖

    >mongodb和mysql为基本的数据库配置和帮助类

    >controllers文件夹下的接口引用mongodb和mysql操作数据库

    >controller.js是对controllers文件夹的引用和设置api路由跳转

    >app.js 加载controller.js文件,即加载所有的controllers文件夹下的接口

    VUE+Node.js接口调用步骤

    MySql数据库准备

    >mysql 添加测试数据库 rehab(数据库名只需要和mysqlconfigindex.js中配置文件的数据库名对应起来就行)

    >添加测试表test{id:int,name:varchar}

    Node.js接口部分(示例中不考虑mongodb数据库使用部分)

    1、创建node.js项目,向package.json中写入项目需要的依赖文件,依次是

    {
      "name": "node-demo",
      "version": "1.0.0",
      "description": "node demo",
      "main": "app.js",
      "scripts": {
        "start": "supervisor app.js"
      },
      "keywords": [
        "koa",
        "async"
      ], 
      "author": "Michael Liao",
      "license": "Apache-2.0",
      "repository": {
        "type": "git",
        "url": "https://github.com/michaelliao/learn-javascript.git"
      },
      "dependencies": {
        "koa": "^2.8.1",
        "koa-bodyparser": "^4.2.1",
        "koa-router": "^7.4.0",
        "mongodb": "^3.3.2",
        "mysql": "^2.17.1",
        "q": "^1.5.1",
        "log4js": "^5.2.0"
      }
    }
    package.json

    koa:koa框架

    koa-bodyparser:解析表单数据,并放入到ctx.request.body

    koa-router:路由

    mongod:node的mongodb数据库中间件

    mysql:node的mysql数据库中间件

    q:Promise处理模块

    log4js:日志文件

    2、controller.js ,设置GETPOSTPUTDELETE四种接口的路由,并把controllers文件夹下的所有js文件加载进来

    const fs = require('fs');
    
    // add url-route in /controllers:
    
    function addMapping(router, mapping) {
        for (var url in mapping) {
            if (url.startsWith('GET ')) {
                var path = url.substring(4);
                router.get(path, mapping[url]);
               // console.log(`register URL mapping: GET ${path}`);
            } else if (url.startsWith('POST ')) {
                var path = url.substring(5);
                router.post(path, mapping[url]);
               // console.log(`register URL mapping: POST ${path}`);
            } else if (url.startsWith('PUT ')) {
                var path = url.substring(4);
                router.put(path, mapping[url]);
                console.log(`register URL mapping: PUT ${path}`);
            } else if (url.startsWith('DELETE ')) {
                var path = url.substring(7);
                router.del(path, mapping[url]);
              //  console.log(`register URL mapping: DELETE ${path}`);
            } else {
                console.log(`invalid URL: ${url}`);
            }
        }
    }
    
    function addControllers(router, dirs) {
        for(let i=0;i<dirs.length;i++){
            fs.readdirSync(__dirname + '/' + dirs[i]).filter((f) => {
                return f.endsWith('.js');
            }).forEach((f) => {
              //  console.log(`process controller: ${f}...`);
                let mapping = require(__dirname + '/' + dirs[i] + '/' + f);
                addMapping(router, mapping);
            });
        }
      
    }
    
    module.exports = function (dir) {
        let
            controllers_dir = dir || 'controllers',
            router = require('koa-router')();
            debugger
            let controllers=['controllers','controllers/admin']
        addControllers(router, controllers);
       // addControllers(router, 'controllers/admin');
        return router.routes();
    };
    
    
    // function addControllers(router, dir) {
    //     fs.readdirSync(__dirname + '/' + dir).filter((f) => {
    //         return f.endsWith('.js');
    //     }).forEach((f) => {
    //         console.log(`process controller: ${f}...`);
    //         let mapping = require(__dirname + '/' + dir + '/' + f);
    //         addMapping(router, mapping);
    //     });
    // }
    
    // module.exports = function (dir) {
    //     let
    //         controllers_dir = dir || 'controllers',
    //         router = require('koa-router')();
    //         debugger
    //     addControllers(router, controllers_dir);
    //    // addControllers(router, 'controllers/admin');
    //     return router.routes();
    // };
    controller.js

    3、app.js

    const Koa = require('koa');
    
    const bodyParser = require('koa-bodyparser');
    
    const controller = require('./controller');
    
    const app = new Koa();
    
    //log4js 日志配置
    var log4js = require('log4js');
    log4js.configure('./config/log4js.json');
    
    // log request URL:
    app.use(async (ctx, next) => {
        //添加允许请求头
        ctx.append('Access-Control-Allow-Origin', '*')
        ctx.append('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild')
        // ctx.append('Content-Type', 'application/json;charset=utf-8')
        ctx.append('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS,PATCH')
        console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
        //http 预请求处理(post/put/delete 请求在正式请求之前会先发送一个OPTIONS的预请求,只需要把这个OPTIONS的预请求正常返回,后续的请求就会正常执行)
        if (ctx.request.method === 'OPTIONS') {
            ctx.body = "OK"
        } else {
            //继续执行api请求
            await next();
        }
    
    });
    
    // parse request body:
    app.use(bodyParser());
    
    // add controller:
    app.use(controller());
    
    app.listen(3000);
    console.log('app started at port 3000...');
    app.js

    app.js做的事情是

    >加载koa框架

    >加载form参数解析的中间件koa-bodyparser

    >加载log4js日志配置文件

    {
        "appenders": {
          "console": {
            "type": "console"
          },
          "trace": {
            "type": "dateFile",
            "filename": "./logs/access-",
            "pattern": ".yyyy-MM-dd.log",
            "alwaysIncludePattern": true,
            "maxLogSize ": 31457280
          },
          "http": {
            "type": "logLevelFilter",
            "appender": "trace",
            "level": "trace",
            "maxLevel": "trace"
          },
          "info": {
            "type": "dateFile",
            "filename": "./logs/info-",
            "encoding": "utf-8",
            "pattern": ".yyyy-MM-dd.log",
            "maxLogSize": 10000000,
            "alwaysIncludePattern": true,
            "layout": {
              "type": "pattern",
              "pattern": "[%d{ISO8601}][%5p  %z  %c] %m"
            },
            "compress": true
          },
          "maxInfo": {
            "type": "logLevelFilter",
            "appender": "info",
            "level": "debug",
            "maxLevel": "error"
          },
          "error": {
            "type": "dateFile",
            "filename": "./logs/error-",
            "pattern": ".yyyy-MM-dd.log",
            "maxLogSize": 10000000,
            "encoding": "utf-8",
            "alwaysIncludePattern": true,
            "layout": {
              "type": "pattern",
              "pattern": "[%d{ISO8601}][%5p  %z  %c] %m"
            },
            "compress": true
          },
          "minError": {
            "type": "logLevelFilter",
            "appender": "error",
            "level": "error"
          }
        },
        "categories": {
          "default": {
            "appenders": [
              "console",
              "http",
              "maxInfo",
              "minError"
            ],
            "level": "all"
          }
        }
      }
    log4js.json

    >加载api路由 controller.js

    >请求url处理

    app.use(async (ctx, next) => {
        //添加允许请求头
        ctx.append('Access-Control-Allow-Origin', '*')
        ctx.append('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild')
        // ctx.append('Content-Type', 'application/json;charset=utf-8')
        ctx.append('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS,PATCH')
        console.log(`Process ${ctx.request.method} ${ctx.request.url}...`);
        //http 预请求处理(post/put/delete 请求在正式请求之前会先发送一个OPTIONS的预请求,只需要把这个OPTIONS的预请求正常返回,后续的请求就会正常执行)
        if (ctx.request.method === 'OPTIONS') {
            ctx.body = "OK"
        } else {
            //继续执行api请求
            await next();
        }
    });

      >>ctx.append()

        添加请求头,目的在服务器端解决跨域问题

      >> ctx.request.method === 'OPTIONS'处理

        请求在正式请求之前会先发送一个OPTIONS的预请求,只需要把这个OPTIONS的预请求正常返回,后续的请求就会正常执行

      >>await next()

        当一个中间件调用 next() 则该函数暂停并将控制传递给定义的下一个中间件。当在下游没有更多的中间件执行后,堆栈将展开并    且每个中间件恢复执行其上游行为。

    >启动端口监听,启动项目

    4、api接口(以处理mysql数据的接口为例)

    controllers文件夹下创建mysqlapi.js文件

    let util = require('../utils/util')
    const db = require('../mysql/mysql.js')
    var logger = require('log4js').getLogger("index");
    let util_http = require('../utils/util_http')
    
    
    module.exports = {
    
        /**
         * 根据数据表名查询全部
         */
        'GET /mysql/findAll': async (ctx, next) => {
            ctx.response.type = 'application/json';
    
            let table = ctx.request.query.table
            let sql = `select * from ${table}`
            await db.selectAll(sql).then(res => {
                ctx.body = util.res(res)
            }).catch(err => {
                ctx.body = util.err(err)
            })
        },
        /**
         * 根据数据表名和指定查询条件查询
         */
        'GET /mysql/findBy': async (ctx, next) => {
            ctx.response.type = 'application/json';
            ctx.append('Access-Control-Allow-Origin', '*')
            let table = ctx.request.body.table
            let where = ctx.request.body.where
            await db.selectBy(table, where).then(res => {
                ctx.body = util.res(res)
    
            }).catch(err => {
                ctx.body = util.err(err)
            })
        },
        /**
         * 根据数据表名和id查询
         */
        'GET /mysql/findById': async (ctx, next) => {
            ctx.response.type = 'application/json';
            ctx.append('Access-Control-Allow-Origin', '*')
            let table = ctx.request.query.table
            let id = ctx.request.query.id
            let sql = `select * from ${table} where id='${id}'`
            await db.selectAll(sql).then(res => {
                ctx.body = util.res(res)
    
            }).catch(err => {
                ctx.body = util.err(err)
            })
        },
    
        /**
         * 添加数据
         */
        'POST /mysql/add': async (ctx, next) => {
            // ctx.response.type = 'application/json'; 
            // ctx.res.header('Access-Control-Allow-Origin', '*');
    
            if (ctx.req.method == 'POST') {
                let data = await util_http.getPOSTRes(ctx.req)
                data = JSON.parse(data)
                let table = data.table
                let params = data.params
                await db.insertData(table, params).then(res => {
                    ctx.body = util.res(res)
                }).catch(err => {
                    ctx.body = util.err(err)
                })
            } else {
                ctx.body = util.err('请求错误')
            }
    
    
        },
        /**
         * 更新数据
         */
        'PUT /mysql/update': async (ctx, next) => {
            if (ctx.req.method == 'PUT') {
                let data = await util_http.getPOSTRes(ctx.req)
                data = JSON.parse(data)
                let table = data.table
                let sets = data.sets
                let where = data.where
               // console.log('sql', table, sets, where)
                await db.updateData(table, sets, where).then(res => {
                    ctx.body = util.res(res)
                }).catch(err => {
                    ctx.body = util.err(err)
                })
            } else {
                ctx.body = util.err('请求错误')
            }
        },
        // /**
        //  * 更新数据
        //  */
        // 'PATCH /mysql/patch': async (ctx, next) => {
        //     // ctx.response.type = 'application/json';
        //     console.log('patch init')
        //     ctx.body = '2222'
        //     //ctx.body=util.res('123')
        //     // console.log('request',ctx.request)
        //     // let table = ctx.request.body.table
        //     // console.log('table',table)
        //     // let sets = ctx.request.body.sets
        //     // let where = ctx.request.body.where
        //     // await db.updateData(table, sets, where).then(res => {
        //     //     ctx.body = util.res(res)
        //     // }).catch(err => {
        //     //     ctx.body = util.err(err)
        //     // })
        // },
        /**
         * 删除数据
         */
        'DELETE /mysql/delete': async (ctx, next) => {  
            let table = ctx.request.body.table
            let where = ctx.request.body.where
            await db.deleteData(table, where).then(res => {
                ctx.body = util.res(res)
            }).catch(err => {
                ctx.body = util.err(err)
            })
        },
        /**
         * 根据数据表名和id删除数据
         */
        'DELETE /mysql/deleteById': async (ctx, next) => {
            ctx.response.type = 'application/json';
            ctx.append('Access-Control-Allow-Origin', '*')
            let table = ctx.request.query.table
            let id = ctx.request.query.id
            let where = {
                id: id
            }
            await db.deleteData(table, where).then(res => {
                ctx.body = util.res(res)
            }).catch(err => {
                ctx.body = util.err(err)
            })
        }
    };
    node.js api接口示例

    >get 接口中使用ctx.request.query接收Params方式传递的表单参数

    >post接口中使用ctx.request.body接收body方式传递的表单参数

      >>post接口中,需要使用监听方式接收表单数据(req.on('data',(chunk)=>{}))+req.on('end',()=>{}))

    let util_http={
        /**
         * 接口执行成功统一回复格式
         * @param {*} result 返回结果 
         * @param {*} code 返回代码
         * @param {*} msg 返回消息
         */
        async getPOSTRes(req){
           return new Promise((resolve,reject)=>{
            let data = '';
            //2.注册data事件接收数据(每当收到一段表单提交的数据,该方法会执行一次)
            req.on('data', function (chunk) {
                // chunk 默认是一个二进制数据,和 data 拼接会自动 toString
                data += chunk;
            });
    
            // 3.当接收表单提交的数据完毕之后,就可以进一步处理了
            //注册end事件,所有数据接收完成会执行一次该方法
            req.on('end', function () {
                //(1).对url进行解码(url会对中文进行编码)
                data = decodeURI(data);
                resolve(data)
            });
           })
        }
       
    }
    
    module.exports=util_http
    body表单数据接收

      接收参数时(包括接口中调用mysql接口时),均需要借助async,await关键字,将代码执行的控制权交给下一级中间件,待下一级中间件执行完成后,继续后续代码操作

    另附mysql文件夹下的mysql配置文件和mysql操作文件

    const mysql = require('mysql')
    
    const connectdb=()=>{
      let connection = mysql.createConnection({
        host     : 'localhost',
        port     : '3306',
        user     : 'root',
        password : '',
        database : 'rehab'
      }) 
      return connection;
    }
    
    module.exports=connectdb;
    mysql配置文件
    const conn = require('./config/index');
    const connection = conn();
    
    // 查询所有数据
    let selectAll = async(sql,callback)=>{
      return sqlQuery(sql)
    }
    let selectBy = async(table,where,callback)=>{
        var _WHERE='';
        // var keys='';
        // var values='';
        for(var k2 in where){
            _WHERE+=k2+"='"+where[k2]+"' AND ";
          //_WHERE+= k2+"='"+where[k2]+"'";
        }
        _WHERE=_WHERE.slice(0,-5)
        // UPDATE user SET Password='321' WHERE UserId=12
        //update table set username='admin2',age='55'   where id="5";
        var sql="SELECT * FROM "+table+' WHERE '+_WHERE;
       // console.log(sql);
        return sqlQuery(sql)
    }
    // 插入一条数据
    let insertData =async (table,datas,callback)=>{
      var fields='';
      var values='';
      for( var k in datas){
          fields+=k+',';
          values=values+"'"+datas[k]+"',"
      }
      fields=fields.slice(0,-1);
      values=values.slice(0,-1);
     // console.log(fields,values);
      var sql="INSERT INTO "+table+'('+fields+') VALUES('+values+')';
      return sqlQuery(sql)
    }
    
    /**
     * 更新一条数据
     * @param {*} table 数据表名
     * @param {*} sets 更新字段
     * @param {*} where 限制条件
     */
    let updateData=async function(table,sets,where){
        var _SETS='';
        var _WHERE='';
        var keys='';
        var values='';
        for(var k in sets){
            _SETS+=k+"='"+sets[k]+"',";
        }
        _SETS=_SETS.slice(0,-1);
        for(var k2 in where){
            _WHERE+=k2+"='"+where[k2]+"' AND ";
          //_WHERE+= k2+"='"+where[k2]+"'";
        }
        _WHERE=_WHERE.slice(0,-5)
        // UPDATE user SET Password='321' WHERE UserId=12
        //update table set username='admin2',age='55'   where id="5";
        var sql="UPDATE "+table+' SET '+_SETS+' WHERE '+_WHERE;
       // console.log(sql);
        return sqlQuery(sql)
    }
    
    // 删除一条数据
    let deleteData=function(table,where,callback){
        var _WHERE='';
        for(var k2 in where){
           _WHERE+=k2+"='"+where[k2]+"' AND ";
          //_WHERE+= k2+"="+where[k2];
        }
        _WHERE=_WHERE.slice(0,-5)
        // DELETE  FROM user WHERE UserId=12  注意UserId的数据类型要和数据库一致
        var sql="DELETE  FROM "+table+' WHERE '+_WHERE;
       // connection.query(sql,callback);
        return sqlQuery(sql)
    }
    
    let sqlQuery=function(sql){
      return new Promise((resolve,reject)=>{
        connection.query(sql,(err,result)=>{
          if(err){
              console.log('错误信息-',err.sqlMessage);
              let errNews = err.sqlMessage;
              reject(errNews)
          } else{
            resolve(result)
          }
        })
      })
    }
    module.exports = {
      selectAll,
      selectBy,
      insertData,
      deleteData,
      updateData,
    }
    mysql操作文件

    VUE操作(接口调用操作)

    1、Vue-cli 3.0搭建项目,配置package.json项目依赖,添加vue.js文件,配置vue文件路由,main.js的组件引用操作省略

    2、测试文件

    <template>
    <div class="api">
        <div class="api-item">
            <van-button type="default" @click="getTest">get test</van-button>
        </div>
        <div class="api-item">
            <van-field v-model="name.add" placeholder="请输入name" />
            <van-button type="default" @click="addTest">add test</van-button>
        </div>
        <div class="api-item">
            <van-field v-model="name.update_set" placeholder="请输入更改值" />
            <van-field v-model="name.update_where" placeholder="请输入初始值" />
            <van-button type="default" @click="updateTest">update test</van-button>
        </div>
        <div class="api-item">
            <van-field v-model="name.delete" placeholder="请输入删除值" />
            <van-button type="default" @click="deleteTest">delete test</van-button>
        </div>
        <div class="api-item api-result">
            <p>result:</p>
            <p>code:{{result.code}}</p>
            <p>msg:{{result.msg}}</p>
            <p>result:{{result.result}}</p></div>
    </div>
    </template>
    
    <script>
        import {api} from "../../api/server";
    
        export default {
            name: "apitest",
            data(){
                return{
                    openid:'28d91cb4-28a6-4110-b401-a6ca03cddf27',
                    result:'',
                    name:{
                        add:'22',
                        update_set:'44',
                        update_where:'33',
                        delete:'2233'
                    },
                    msg:''
                }
            },
            methods:{
                getTest(){
                    let params={
                        table:'test'
                    }
                    let that=this;
                    api.get(params).then(res=>{
                        console.log('res',res)
                        that.result=res
                    }).catch(err=>{
                        console.log('err',err)
                        that.result=err
                    })
                },
                addTest(){
                    if(this.name.add==''){
                        this.Toast('请输入name');
                        return false
                    }
                    let params= {
                        table: 'test',
                        params: {
                            id: this.util.randomNum(),
                            name: this.name.add
                        }
                    }
                    let that=this;
                    api.add(params).then(res=>{
                        console.log('res',res)
                        that.result=res
                    }).catch(err=>{
                        console.log('err',err)
                        that.result=err
                    })
                },
                updateTest(){
                    if(this.name.update_where==''||this.name.update_set==''){
                        this.Toast('请输入name');
                        return false
                    }
                    let params= {
                        table: 'test',
                        sets: {
                            name:this.name.update_set
                        },
                        where: {
                            name:this.name.update_where
                        }
                    }
                    // let params={
                    //     id:'11',
                    //     name:'22'
                    // }
                    let that=this;
                    api.update(params).then(res=>{
                        console.log('res',res)
                        that.result=res
                    }).catch(err=>{
                        console.log('err',err)
                        that.result=err
                    })
                },
                deleteTest(){
                    if(this.name.update_where==''||this.name.update_set==''){
                        this.Toast('请输入name');
                        return false
                    }
                    let params= {
                        table: 'test',
                        where: {
                            name:this.name.delete
                        }
                    }
                    // let params={
                    //     id:'11',
                    //     name:'22'
                    // }
                    let that=this;
                    api.delete(params).then(res=>{
                        console.log('res',res)
                        that.result=res
                    }).catch(err=>{
                        console.log('err',err)
                        that.result=err
                    })
                },
            }
        }
    </script>
    
    <style lang="less" scoped>
    .api{
        text-align: left;
        background-color: #ffffff;
        .api-item{
            margin: 8px;
        }
    }
    </style>
    vue测试页

     3、api接口

    import axios from 'axios';
     const server = 'http://localhost:3000';
    
    export  const api={
        get(params){
            return axios.get(server + '/mysql/findAll', {params});
        },
        add(params){
          let headers = {'Content-Type': 'multipart/form-data'}
           return axios.post(server + '/mysql/add', params, {headers});
        },
        update(params){
             let headers = {'Content-Type': 'multipart/form-data'}
           return axios.put(server + '/mysql/update', params,{headers});
        },
        delete(params){
            let headers = {'Content-Type': 'multipart/form-data'}
            return axios.delete(server + '/mysql/delete', {data:params},{headers});
        },
    }
    vue api接口

    > 示例中使用的是axios组件调用的api接口

    > params接口参数形式说明

      >> get接口参数需要使用{}包裹,如{params}

      >> postput接口直接添加params参数

      >> delete接口需加上'data'说明,如{data:params}

    >headers

      >> postputdelete三种方式需要添加请求头header设置 headers = {'Content-Type': 'multipart/form-data'}

      在node.js中接收方式为ctx.request.body

      >> get方式请求不需要加请求头,在node.js中接收方式为ctx.request.query

      >> putdelete 请求方式在发送请求前会先发送预请求命令,请求方式为OPTIONS,这时只需要在node.js中正常返回,不需要做任何处理

    最后,展示几种接口在postman中的调用方式

     

  • 相关阅读:
    final和finally的区别
    ArrayList和LinkedList的区别
    collection和collections的区别
    第三次作业
    第二次作业
    第零次作业
    最后一次作业-- 总结报告
    第14、15教学周作业
    GridView去掉边框! 【转载于:http://magicpeng99.blog.sohu.com/】
    ASP.NET支持用Menu显示web.sitemap中定义好的网站链接 【转载】
  • 原文地址:https://www.cnblogs.com/eye-like/p/11743744.html
Copyright © 2011-2022 走看看