Node.js - Express

祁曦哲
2023-12-01

Node.js - Express

环境配置

工具

Node.js
Express

Express安装

npm install -g express

npm install -g express-generator

npm install body-parser -g

npm install cookie-parser -g

npm install multer -g

创建项目

D:\workspace_node>express maoyan
warning: the default view engine will not be jade in future releases
warning: use --view=jade' or–help’ for additional options
create : maoyan
create : maoyan\public
create : maoyan\public\javascripts
create : maoyan\public\images
create : maoyan\public\stylesheets
create : maoyan\public\stylesheets\style.css
create : maoyan\routes
create : maoyan\routes\index.js
create : maoyan\routes\users.js
create : maoyan\views
create : maoyan\views\error.jade
create : maoyan\views\index.jade
create : maoyan\views\layout.jade
create : maoyan\app.js
create : maoyan\package.json
create : maoyan\bin
create : maoyan\bin\www
change directory:
cd maoyan
install dependencies:
npm install
run the app:
SET DEBUG=maoyan:* & npm start

express myapp

cd myapp

npm install

npm install mysql mongodb mongoose express-session cookie-parser

封装了网络的处理,如何接收一个tcp连接,如何收取http协议包中的内容,如何处理并发请求,如何处理响应数据。

NPM环境配置

先配置npm的全局模块的存放路径以及cache路径:
npm config set prefix “D:\Program Files (x86)\nodejs\node_global”
npm config set cache “D:\Program Files (x86)\nodejs\node_cache”

开发步骤

跨域

var app = express();
app.all("", function (req, res, next) {
res.header(“Access-Control-Allow-Origin”, "
");
res.header(“Access-Control-Allow-Headers”, “X-Requested-With”);
res.header(“Access-Control-Allow-Methods”, “PUT,POST,GET,DELETE”);
res.header(“Content-Type”, “application/json;charset=utf-8”);
next();
})

app.js定义路由

var student = require(’./routes/student’);//学生
app.use(’/student’, student);

路由js文件中定义api请求

var $ = require(’…/controllers/Student_Controller’);
router.route(’/’)
.get( . l i s t ) . p o s t ( .list) .post( .list).post(.create);
router.route(’/:id’)
.post( . u p d a t e ) . g e t ( .update) .get( .update).get(.get)
.delete($.delete);
module.exports = router;

控制层Student_Controller实现具体的接口

var dao = require(’…/models/StudentDao’);
exports.list = function (req, res, next) {
console.log(req.method + ’ /student, GetReq: ’ + JSON.stringify(req.query) +
', PostReq: ’ + JSON.stringify(req.body));
}

常用功能

app.use pk app.all

app.use 只带一个回调函数;通常不处理请求和应答,只处理输入数据并转给下一个;

1.inject middlware to your front controller configuring for instance: header, cookies, sessions, etc.
2.must be written before app[http_method] otherwise there will be not executed.
3.several calls are processed in the order of writing

app.use([path], function)

app.use only sees whether url starts with the specified path

app.use( “/product” , mymiddleware);
// will match /product
// will match /product/cool
// will match /product/foo

app.all 带多个回调函数,匹配完整路径

1、(like app[http_method]) is used for configuring routes’ controllers
2、“all” means it applies on all http methods.
3、several calls are processed in the order of writing

app.all(path, [callback…], callback)
app.all( “/product” , handler);
// will match /product
// won’t match /product/cool <-- important
// won’t match /product/foo <-- important
app.all( “/product/*” , handler);
// won’t match /product <-- Important
// will match /product/
// will match /product/cool
// will match /product/foo

app.use(’/admin’, function(req, res, next) {
// GET ‘http://www.example.com/admin/new
console.log(req.originalUrl); // ‘/admin/new’
console.log(req.baseUrl); // ‘/admin’
console.log(req.path); // ‘/new’
next();
});

路径匹配

// will match paths starting with /abcd
app.use(’/abcd’, function (req, res, next) {
next();
})
// will match paths starting with /abcd and /abd
app.use(’/abc?d’, function (req, res, next) {
next();
})
// will match paths starting with /abcd, /abbcd, /abbbbbcd and so on
app.use(’/ab+cd’, function (req, res, next) {
next();
})
// will match paths starting with /abcd, /abxcd, /abFOOcd, /abbArcd and so on
app.use(’/ab*cd’, function (req, res, next) {
next();
})
// will match paths starting with /ad and /abcd
app.use(’/a(bc)?d’, function (req, res, next) {
next();
})
// will match paths starting with /abc and /xyz
app.use(//abc|/xyz/, function (req, res, next) {
next();
})
// will match paths starting with /abcd, /xyza, /lmn, and /pqr
app.use([’/abcd’, ‘/xyza’, //lmn|/pqr/], function (req, res, next) {
next();
})

中间件

var router = express.Router();
router.get(’/’, function (req, res, next) {
next();
})
app.use(router);
var subApp = express();
subApp.get(’/’, function (req, res, next) {
next();
})
app.use(subApp);
var r1 = express.Router();
r1.get(’/’, function (req, res, next) {
next();
})
var r2 = express.Router();
r2.get(’/’, function (req, res, next) {
next();
})
app.use(r1, r2);
var r1 = express.Router();
r1.get(’/’, function (req, res, next) {
next();
})
var r2 = express.Router();
r2.get(’/’, function (req, res, next) {
next();
})
app.use(’/’, [r1, r2]);

文件目录

// GET /style.css etc
app.use(express.static(__dirname + ‘/public’));
// GET /static/style.css etc.
app.use(’/static’, express.static(__dirname + ‘/public’));
app.use(express.static(__dirname + ‘/public’));
app.use(logger());
app.use(express.static(__dirname + ‘/public’));
app.use(express.static(__dirname + ‘/files’));
app.use(express.static(__dirname + ‘/uploads’));

配置http应答头

res.append(‘Link’, [‘http://localhost/’, ‘http://localhost:3000/’]);
res.append(‘Set-Cookie’, ‘foo=bar; Path=/; HttpOnly’);
res.append(‘Warning’, ‘199 Miscellaneous warning’);
res.set(‘Content-Type’, ‘text/plain’);
res.set({
‘Content-Type’: ‘text/plain’,
‘Content-Length’: ‘123’,
‘ETag’: ‘12345’
})
jsonp
// ?callback=foo
res.jsonp({ user: ‘tobi’ })
// => foo({ “user”: “tobi” })

重定向

res.location(’/foo/bar’);
res.location(‘http://example.com’);
res.location(‘back’);
res.redirect(’/foo/bar’);
res.redirect(‘http://example.com’);
res.redirect(301, ‘http://example.com’);
res.redirect(’…/login’);

指定错误代码

res.status(404).send(‘Sorry, we cannot find that!’);
res.status(500).send({ error: ‘something blew up’ });
router
http://www.expressjs.com.cn/4x/api.html#router.param
router.all(’’, requireAuthentication, loadUser);

router.all(’
’, requireAuthentication)
router.all(’*’, loadUser);
//多个函数处理
//GET /user/42时:
CALLED ONLY ONCE
although this matches
and this matches too
router.param(‘id’, function (req, res, next, id) {
console.log(‘CALLED ONLY ONCE’);
next();
})
app.get(’/user/:id’, function (req, res, next) {
console.log(‘although this matches’);
next();
});
app.get(’/user/:id’, function (req, res) {
console.log(‘and this matches too’);
res.end();
});
//GET /user/42/3
CALLED ONLY ONCE with 42
CALLED ONLY ONCE with 3
although this matches
and this matches too
router.param([‘id’, ‘page’], function (req, res, next, value) {
console.log(‘CALLED ONLY ONCE with’, value);
next();
})
app.get(’/user/:id/:page’, function (req, res, next) {
console.log(‘although this matches’);
next();
});
app.get(’/user/:id/:page’, function (req, res) {
console.log(‘and this matches too’);
res.end();
});

链式调用

router.route(’/users/:user_id’)
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
next();
})
.get(function(req, res, next) {
res.json(req.user);
})
.put(function(req, res, next) {
// just an example of maybe updating the user
req.user.name = req.params.name;
// save user … etc
res.json(req.user);
})
.post(function(req, res, next) {
next(new Error(‘not implemented’));
})
.delete(function(req, res, next) {
next(new Error(‘not implemented’));
})

跨域

cors跨域

后端web服务器的应答头中,添加允许跨域的配置。
express

app.all(’’, function(req, res, next) {
res.header(“Access-Control-Allow-Origin”, "
");
res.header(“Access-Control-Allow-Headers”, “Content-Type,Content-Length, Authorization, Accept,X-Requested-With”);
res.header(“Access-Control-Allow-Methods”,“PUT,POST,GET,DELETE,OPTIONS”);
res.header(“X-Powered-By”,’ 3.2.1’)
if(req.method==“OPTIONS”)
res.send(200);/让options请求快速返回/
else
next();
});

koa2

app.use(async function(ctx,next){
ctx.set(“Access-Control-Allow-Origin”, “*”);
ctx.set(“Access-Control-Allow-Headers”, “Content-Type,Content-Length, Authorization, Accept,X-Requested-With”);
ctx.set(“Access-Control-Allow-Methods”,“PUT,POST,GET,DELETE,OPTIONS”);
ctx.set(“X-Powered-By”,’ 3.2.1’)
if(ctx.method==“OPTIONS”)
ctx.body=‘200’;/让options请求快速返回/
else
await next();
})

代理跨域(通过nginx)

修改hosts文件 c:\windows\system32\drivers\etc\hosts
127.0.0.1 a.com
127.0.0.1 b.com
127.0.0.1 c.com
test.html页面
部署在nginx配置的文件夹下。
function login(){
$.ajax({
url:“http://a.com/apis/users/login”,//请求地址
type:“post”,//请求方式
async:true,//是否异步
data:{
phone:138,
passwd:123456
},
success:function(data){//成功回调
console.log(data)
var uid=data.user.id
var tokenStr=data.user.token
if (window.localStorage) {
localStorage.token = uid+"|"+tokenStr
}
console.log(localStorage.token)
},
error:function(xhr){//失败回调
console.log(xhr.status)
},
});
}

nginx配置:

server {
listen 80;
server_name a.com;
charset utf-8;
access_log logs/a.access.log main;
location / {
root html;
index index.html index.htm;
}
location /apis { #添加访问目录为/apis的代理配置
rewrite ^/apis/(.*)$ /$1 break;
proxy_pass http://localhost:3000;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}

浏览器访问

http://a.com/test.html
接口真实地址
http://localhost:3000

MySQL

const mysql = require(‘mysql’);
const config = {
host: ‘localhost’,
port: 6033,
database : ‘maoyan’,
user: ‘root’,
password: ‘123456’,
}

//创建数据池

const pool = mysql.createPool(config);
var query = function (sql, datas) {
var p = new Promise((resolve,reject)=>{
pool.getConnection(function(err,connection){
if(err)
reject(err)
else{
connection.query(sql,datas,function(error,results){
if(error)
reject(error)
else
resolve(results)
connection.release();//释放链接
})
}
})
});
return p;
}
exports.insert = function(tableName, obj){
var columns = “”;//insert into tb_xxx(col1,col2) value(?,?)
var symbols = “”;
var data = [];
for (key in obj) {
console.log(key);
console.log(obj[key]);
columns += (columns.length > 0 ? “,” : “”) + key
symbols += (symbols.length > 0 ? “,” : “”) + “?”
data.push(obj[key]);
}
console.log(data)
var sql = “insert into " + tableName + “(” + columns + “) value(” + symbols + “)”;
console.log(sql)
return query(sql,data);
}
exports.query = query;
exports.delete = query;
exports.update = query;
//select A.,B. from tb_A A, tb_B B where A.x=B.y and A.id=? and B.name=?..
//update tb_A set name=?,nick=? where id=? // [”","",""]
//delete from tb_A where id=? // id in (?) // [2]
//insert into tb_A(name,nick,password,phone,regdate) values(?,?,?,?,now()) // ["","","",""]

Express-MongoDB

Express-Redis
https://www.jianshu.com/p/313e01c68219
Express-Session

session会话

npm install express-session -s

app.js中:

let session=require(‘express-session’)
//开启session中间件
app.use(session({
secret: ‘123456’,
name: ‘sessionId’, //这里的name值得是cookie的name,默认cookie的name是:connect.sid
cookie: {maxAge: 80000 }, //设置maxAge是80000ms,即80s后session和相应的cookie失效过期
resave: false,
saveUninitialized: true,
}));
//如果服务器开启了session,浏览器跟服务器第一次交互的应答Response,都会得到sessionId(通过set-cookie得到的sessionId)
//之后的任何浏览器请求Requset都会带上sessionId(通过cookie带上)
express内存里面
sessionId_1
req.session 对象
user
{id:1 name: }
loginuser
uid
1
sessionId_2
req.session 对象
user
{id: 2 name: }
loginuser
uid
2
sessionId_3
session对象
req.session

参考文章:https://www.cnblogs.com/muamaker/p/6806895.html

 类似资料: