
ASP.NET Web API快速入門介紹
package.json文件
每個Nodejs項目的根目錄下面,一般都會有一個package.json文件。該文件可以由npm init生成,定義了項目所需要的各種模塊,以及項目的配置信息(比如名稱、版本、許可證等元數據)。package.json文件內部就是一個JSON對象,該對象的每一個成員就是當前項目的一項設置。
mysql模塊是node操作MySQL的引擎,可以在node.js環境下對MySQL數據庫進行建表,增、刪、改、查等操作。
"dependencies": {
"glob": "^7.1.3",
"jsonwebtoken": "^8.4.0",
"koa": "^2.6.2",
"koa-body": "^4.0.4",
"koa-bodyparser": "^4.2.1",
"koa-cors": "0.0.16",
"koa-jwt": "^3.5.1",
"koa-router": "^7.4.0",
"koa-session": "^5.10.0",
"koa-static": "^5.0.0",
"mysql": "^2.16.0"
}
在package.json依賴中設置”mysql”: “^2.16.0”
const config = require('../config').database
const mysql = require('mysql')
const pool = mysql.createPool(config)
const query = function(sql,succCb,errCb){
pool.getConnection(function(err,conn){
if (err) {
let data = {
code:500,
message:"請求失敗",
data:err
};
errCb(data);
}else {
conn.query(sql,function(err,result){
if (err) {
let data = {
code:500,
message:"請求失敗",
data:err
};
errCb(data);
}else {
succCb(result);
conn.release();
}
})
}
})
}
module.exports = query;
const query = require('./query')
const Tools = require('./tools')
const mysql = require('mysql')
const config = require('../config').database
const pool = mysql.createPool(config)
const getByPage = function(tb,page,limit){
return new Promise((resolve,reject)=>{
let start = (page-1)*limit;
let command = select * from ${tb} limit ${start},${limit}
;
query(command,function(res){
let data = {
code:200,
message:'獲取成功',
data:{
list:res,
pagination:{
size:res.length,
currentPage:parseInt(page)
}
}
}
query(select count(*) from ${tb}
,function(res){
data.data.pagination['total'] = res[0]["count(*)"];
data.data.pagination['totalPage'] = parseInt(res[0]["count(*)"]/limit) + ((res[0]["count(*)"]%limit)>0?1:0);
resolve(data);
},function(err){
resolve(data)
})
},function(err){
resolve(err);
})
})
}
const getForeignInfo = function(tb,filter,foreign){//主表,篩選條件,外鍵信息
let queryStr = '';//查詢條件
for (let key in filter) {
queryStr += ${tb}.${key}=${filter[key]}&
;
}
queryStr = queryStr.substr(0,queryStr.length-1);
let as = '';
let join = '';
let tables = from ${tb} ${tb}
;
for (let key1 in foreign) {
let table = foreign[key1].table;
let data = foreign[key1].data;
let key = key1;
join += join ${table} ${table} on ${tb}.${key}=${table}.id
;
for(let key2 in data){
as += ,${table}.${key2} as ${data[key2]}
}
}
let str = select ${tb}.*
+as+tables+join+(queryStr==''?'':'where '+queryStr);
console.log(str);
return str;
}
const Sql = {
queryAll:function(tb,filter,foreign){ //獲取表的全部記錄
if (filter && !Tools.isEmptyObject(filter)) { //分頁
return getByPage(tb,filter.page,filter.limit,foreign)
}else { //全部
return new Promise((resolve,reject)=>{
let str = select * from ${tb}
;
if (foreign) {
str = getForeignInfo(tb,filter,foreign);
}
query(str,function(res){
let data = {
code:200,
message:'獲取成功',
data:{
list:res,
size:res.length
}
}
resolve(data);
},function(err){
resolve(err);
})
})
}
},
query:function(tb,id,foreign){ //根據id獲取
return new Promise((resolve,reject)=>{
query(select * from ${tb} where id=${id}
,function(res){
let data = {
code:200,
message:res.length==0?'查無數據':'獲取成功',
data:res.length==0?{}:res[0]
}
resolve(data);
},function(err){
resolve(err);
})
})
},
queryByField:function(tb,fieldName,fieldValue){ //根據field獲取
return new Promise((resolve,reject)=>{
query(select * from ${tb} where ${fieldName}="${fieldValue}"
,function(res){
let data = {
code:200,
message:res.length==0?'查無數據':'獲取成功',
data:res.length==0?{}:res[0]
}
resolve(data);
},function(err){
resolve(err);
})
})
},
insert:function(tb,data){ //插入一條記錄
return new Promise((resolve,reject)=>{
let [keys,values] = [[],[]];
for (let key in data) {
if (data.hasOwnProperty(key)) {
keys.push(key);
if (Object.prototype.toString.call(data[key]) == '[object String]') {
values.push("${data[key]}"
)
}else {
values.push(data[key])
}
}
}
query(insert into ${tb} (${keys}) values (${values})
,function(res){
let id = res.insertId;
let data = {
code:200,
message:'添加成功',
data:res
}
query(select * from ${tb} where id=${id}
,function(res){
data.data = res[0];
resolve(data);
},function(err){
resolve(data);
})
},function(err){
resolve(err);
})
})
},
insertRows:function(tb,arr){ //插入多條記錄
return new Promise((resolve,reject)=>{
let [keys,values] = [[],[]];
for (let i = 0; i < arr.length; i++) {
let [data,value] = [arr[i],[]];
for (let key in data) {
if (data.hasOwnProperty(key)) {
if (i==0) {
keys.push(key);
}
if (Object.prototype.toString.call(data[key]) == '[object String]') {
value.push("${data[key]}"
)
}else {
value.push(data[key])
}
}
}
values.push((${value})
);
}
query(insert into ${tb} (${keys}) values ${values}
,function(res){
let data = {
code:200,
message:'添加成功',
data:res
}
let ids = [];
for (let i = 0; i < res.affectedRows; i++) {
ids.push(res.insertId+i);
}
query(select * from ${tb} where id in (${ids})
,function(res){
data.data = {
list:res,
size:res.length
};
resolve(data);
},function(err){
resolve(data);
})
},function(err){
resolve(err);
})
})
},
update:function(tb,id,data){ //根據id修改單條記錄
return new Promise((resolve,reject)=>{
let [str,index] = ['',0];
for (let key in data) {
if (data.hasOwnProperty(key)) {
if (index!=0) {
str += ','
}
if (Object.prototype.toString.call(data[key]) == '[object String]'){
str += ${key}="${data[key]}"
}
else {
str += ${key}=${data[key]}
}
index++;
}
}
query(update ${tb} set ${str} where id=${id}
,function(res){
let data = {
code:200,
message:'修改成功',
data:res
}
query(select * from ${tb} where id=${id}
,function(res){
data.data = res[0];
resolve(data);
},function(err){
resolve(data);
})
},function(err){
resolve(err);
})
})
},
updateRows:function(tb,arr){ //修改多條記錄
return new Promise((resolve,reject)=>{
let [str,ids,len,keys] = ['',[],arr.length,Object.keys(arr[0])];
for (let x = 0; x < len; x++) {
ids.push(arr[x].id);
}
for (let i = 0; i < keys.length; i++) {
let k = keys[i];
if (k!='id') {
str += ${k} = case id
;
for (let j = 0; j < len; j++) {
str += when ${arr[j].id} then
;
if (Object.prototype.toString.call(arr[j][k]) == '[object String]'){
str += "${arr[j][k]}"
}
else{
str += ${arr[j][k]}
}
}
str += 'end'
if (i<keys.length-1) {
str += ','
}
}
}
query(update ${tb} set ${str} where id in (${ids})
,function(res){
let data = {
code:200,
message:'修改成功',
data:res
}
query(select * from ${tb} where id in (${ids})
,function(res){
data.data = {
list:res,
size:res.length
};
resolve(data);
},function(err){
resolve(data);
})
},function(err){
resolve(err);
})
})
},
delete:function(tb,id){ //根據id刪除單條記錄
return new Promise((resolve,reject)=>{
query(delete from ${tb} where id=${id}
,function(res){
let data = {
code:200,
message:'刪除成功',
data:res
}
resolve(data);
},function(err){
resolve(err);
})
})
},
deleteRows:function(tb,data){ //根據id數組刪除多條記錄
return new Promise((resolve,reject)=>{
query(delete from ${tb} where id in (${data})
,function(res){
let data = {
code:200,
message:'刪除成功',
data:res
}
resolve(data);
},function(err){
resolve(err);
})
})
},
search:function(tb,data,foreign){ //根據條件準確查詢
let queryStr = '';//查詢條件
for (let key in data) {
queryStr += ${key}=${data[key]}&
;
}
queryStr = queryStr.substr(0,queryStr.length-1);
let str;
if (foreign) {
str = getForeignInfo(tb,data,foreign);
}else {
str = select * from ${tb} where ${queryStr}
}
return new Promise((resolve,reject)=>{
query(str,function(res){
resolve({
code:200,
message:'獲取成功',
data:res
});
},function(err){
resolve(err);
});
})
},
searchVague:function(tb,val,fields,foreign){//根據條件模糊查詢
let str = select * from ${tb} where concat(
;
for (let i = 0; i < fields.length; i++) {
str += ${fields[i]},
;
}
str = str.substring(0,str.length-1);
str += ) like %${val}%
;
if (fields.length==1){
str = select * from ${tb} where ${fields[0]} like '%${val}%'
;
}
return new Promise((resolve,reject)=>{
query(str,function(res){
resolve({
code:200,
message:'獲取成功',
data:res
});
},function(err){
resolve(err);
});
})
}
}
module.exports = Sql;
引入?“jsonwebtoken”:?“^8.4.0”,模塊
const jwt = require('jsonwebtoken');
const Token = {
encrypt:function(data,time){ //data加密數據,time過期時間
return jwt.sign(data, 'token', {expiresIn:time})
},
decrypt:function(token){
try {
let data = jwt.verify(token, 'token');
return {
token:true,
id:data.id
};
} catch (e) {
return {
token:false,
data:e
}
}
}
}
module.exports = Token
登錄成功返回token代碼:
token = jwt.sign({id:res[0].id}, 'token', {expiresIn: '15d'})
需求:小程序用戶輸入單詞,返回這個單詞的詳細介紹,包含中文釋義和常用例句。
添加一個routers文件
wordDesc.js
const router = require('koa-router')(); //路由
const Sql = require('../utils/sql');
const query = require('../utils/query');
const Tools = require('../utils/tools');
const jwt = require('jsonwebtoken');
const Token = require('../utils/token')
const tbName = 'worddesc';
const preUrl = '/api/worddesc';
let codeList = {};
api/worddesc/test
.get(${preUrl}/:word
,async(ctx,next)=>{ //獲取word desc
let word = ctx.params.word;
let data = Token.decrypt(ctx.header.authorization);
if (data.token) {
let res = await Sql.queryByField(tbName,"word", word);
ctx.body = res;
}else {
ctx.body = {
code:401,
message:'failed',
data:data
};
}
})
{
"code": 200,
"message": "獲取成功",
"data": {
"id": 2,
"word": "test",
"description": "this is a test.",
"bookid": "2",
"createdtime": null,
"lastupdatetime": null,
"maxl": 2
}
/api/worddesc?page=2&count=2
.get(${preUrl}
,async(ctx,next)=>{ //獲取word desc
let data = Token.decrypt(ctx.header.authorization);
if (data.token) {
let page = ctx.query.page;
if(page == undefined){
page = 1;
}
let count = ctx.query.count;
if(count ==undefined){
count = 500;
}
let filter = {
page:page,
limit:count
}
let res = await Sql.queryAll(tbName,filter);
ctx.body = res;
}else {
ctx.body = {
code:401,
message:'failed',
data:data
};
}
})
{
"code": 200,
"message": "獲取成功",
"data": {
"list": [
{
"id": 2,
"word": "test",
"description": "this is a test.",
"bookid": "2",
"createdtime": null,
"lastupdatetime": null,
"maxl": 2
},
{
"id": 3,
"word": "year3",
"description": "year3",
"bookid": "3",
"createdtime": null,
"lastupdatetime": null,
"maxl": 3
},
{
"id": 4,
"word": "ljtest",
"description": "desc........",
"bookid": "2",
"createdtime": null,
"lastupdatetime": null,
"maxl": null
},
{
"id": 6,
"word": "lj2",
"description": null,
"bookid": null,
"createdtime": null,
"lastupdatetime": null,
"maxl": null
},
{
"id": 7,
"word": "lj3",
"description": null,
"bookid": null,
"createdtime": null,
"lastupdatetime": null,
"maxl": null
},
{
"id": 8,
"word": "lj4",
"description": null,
"bookid": null,
"createdtime": null,
"lastupdatetime": null,
"maxl": null
}
],
"pagination": {
"size": 6,
"currentPage": 1,
"total": 6,
"totalPage": 1
}
}
}
同樣增加添加、修改、刪除api
.post(${preUrl}
,async(ctx,next)=>{ //添加信息
let data = Token.decrypt(ctx.header.authorization);
let word = ctx.request.body.word;
if (data.token) {
let wordRes = await Sql.queryByField(tbName,"word",word);
console.log("------------");
console.log(wordRes);
if(wordRes.data.id != undefined)
{
let res = await Sql.update(tbName,wordRes.data.id,ctx.request.body);
ctx.body = res;
}else{
let res = await Sql.insert(tbName,ctx.request.body);
ctx.body = res;
}
}else {
ctx.body = {
code:401,
message:'failed',
data:data
};
}
})
.delete(${preUrl}/:word
,async(ctx,next)=>{ //修改信息
let data = Token.decrypt(ctx.header.authorization);
let word = ctx.params.word;
if (data.token) {
let wordRes = await Sql.queryByField(tbName,"word",word);
if(wordRes.data.id != undefined)
{
let res = await Sql.delete(tbName,wordRes.data.id );
ctx.body = res;
}else{
ctx.body = {
code:200,
message:'no record',
data:''
};
}
}else {
ctx.body = {
code:401,
message:'failed',
data:data
};
}
})
.put(${preUrl}/:word
,async(ctx,next)=>{ //修改信息
let data = Token.decrypt(ctx.header.authorization);
let word = ctx.params.word;
console.log(word);
if (data.token) {
let wordRes = await Sql.queryByField(tbName,"word",word);
console.log("------------");
console.log(wordRes);
if(wordRes.data.id != undefined)
{
console.log("id------------");
console.log(wordRes.data.id);
console.log(ctx.request.body);
let res = await Sql.update(tbName,wordRes.data.id ,ctx.request.body);
ctx.body = res;
}else{
ctx.body = {
code:200,
message:'no record',
data:''
};
}
}else {
ctx.body = {
code:401,
message:'failed',
data:data
};
}
})
開發過程中命令行輸入 node app.js 可以打開命令窗口啟動運行,窗口中顯示調試或錯誤信息,關閉窗口則結束進程。
生產環境中可以使用pm2來啟動進程,M2是可以用于生產環境的Nodejs的進程管理工具,并且它內置一個負載均衡。它不僅可以保證服務不會中斷一直在線,并且提供0秒reload功能,還有其他一系列進程管理、監控功能。并且使用起來非常簡單。
npm install -g pm2
下面列出常用命令
$ npm install pm2 -g # 命令行安裝 pm2
$ pm2 start app.js -i 4 #后臺運行pm2,啟動4個app.js
# 也可以把'max' 參數傳遞給 start
# 正確的進程數目依賴于Cpu的核心數目
$ pm2 start app.js --name my-api # 命名進程
$ pm2 list # 顯示所有進程狀態
$ pm2 monit # 監視所有進程
$ pm2 logs # 顯示所有進程日志
$ pm2 stop all # 停止所有進程
$ pm2 restart all # 重啟所有進程
$ pm2 reload all # 0秒停機重載進程 (用于 NETWORKED 進程)
$ pm2 stop 0 # 停止指定的進程
$ pm2 restart 0 # 重啟指定的進程
$ pm2 startup # 產生 init 腳本 保持進程活著
$ pm2 web # 運行健壯的 computer API endpoint (http://localhost:9615)
$ pm2 delete 0 # 殺死指定的進程
$ pm2 delete all # 殺死全部進程
通過這次nodejs開發實踐,對于nodejs能夠流行起來一點都不感到意外,開發起來太簡單和方便了。跟java這些傳統的技術相比,寫nodejs腳本甚至感覺不像是在編程,真的像玩一樣,極大了拉低了程序員的門檻。
還有一個事實就是JavaScript是Web開發者們熟知的語言,大部分人都了解JavaScript或多少使用過它。所以說,從其他技術轉型到Node.js是很簡單的。
跟java、.net這些傳統的技術路線相比,nodejs項目在安裝、調試、部署和發布都很方便,很多Web服務器和云服務提供商都支持Node.js的Web應用。
本文章轉載微信公眾號@程序你好