express的使用
一、express简单使用
//创建一个文件夹,进入文件夹
npm i //初始化文件夹,生成package.json文件
//安装express模块
npm install express --save
在项目文件夹下,创建一个app.js文件
//app.js
const express = require("express");
const app = express();
app.get("/", (req, res) => {
res.send("hello world")
})
app.listen(3000)
执行 node app.js, 启动node服务器
二、 Get Post 请求的参数
(一)post请求
● POST 请求在 express 中不能直接获得,可以使用 body-parser 模块。使用后,将可以用
req.body 得到参数。但是如果表单中含有文件上传,那么还是需要使用 formidable 模块。
安装
npm install body-parser
使用
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
//解析 application/x-www-from-urlencoded
//true使用qs第三模块,false使用querystring内置模块
app.use(bodyParser.urlencoded({extended:false}))
//解析 application/json
app.use(bodyParser.json())
//以上两种方法为常用配置,根据需求选择
app.post("/post", (req, res) => {
//通过req.body获得post传值
let result = req.body
res.send(result)
})
(二)get请求
● GET 请求的参数在 URL 中,在原生 Node 中,需要使用 url 模块来识别参数字符串。在
Express 中, 不需要使用 url 模块了。可以直接使用 req.query 对象。
*注意区分动态路由和get传值:
localhost:8080/home/:id //localhost:8080/home/1 通过req.params获得
localhost:8080/home/?id=1 //localhost:8080/home/?id=1 通过req.query获得
三、辅助工具
(一)nodemon
npm install nodemon -g
//启动
nodemon server.js
(二)supervisor代替node命令启动应用(不建议使用)
npm insall supervisor -g
//启动
supervisor server.js
四、使用express脚手架
//全局安装express脚手架
npm install express-generator -g
//创建一个项目
express '项目名称'
//进入项目目录
cd '项目名称'
可以看到生成项目的目录结构如下:
├── app.js
├── bin
│ └── www
├── package-lock.json
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.jade
├── index.jade
└── layout.jade
//安装依赖
npm install
//启动项目
ndoe ./bin/www
五、中间件
Express是一个路由和中间件的Web框架,它本身的功能非常少:
中间件是什么呢?
中间件中可以执行哪些任务呢?
如果当前中间件功能没有结束请求-响应周期
,则必须调用next()将控制权传递给下一个中间件功能,否则,请求将被挂起。
(一)在express使用ejs
安装ejs模块
npm install ejs --save
使用
const express = require('express')
const ejs = require('ejs')
const path = require('path')
const app = express()
app.set("view engine","ejs")
//ejs后缀修改为html
//app.engine("html", ejs._express)
//app.set("view engine", "html")
//指定模板位置,默认模板位置在views
//app.set('views',path.join(__dirname,'views'))
app.get("/ejs", (req, res) => {
res.render("index.ejs", {
//传入的参数
})
})
ejs语法
<%%>
<%=%>
<%-%>
(二)express.static托管静态文件
app.use(express.static("public")) //参数为静态文件存放路径
eg:http://localhost:3000/css/index.css
也可以这样配置
app.use("static", express.static("public"))
则访问时就需要多加上/static
eg:http://localhost:3000/static/css/index.css
这是内置中间件
(三)body-parser第三方中间件
npm install body-parser --save
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
//解析 application/json
app.use(bodyParser.json())
//解析 application/x-www-from-urlencoded
app.use(bodyParser.urlencoded({extended:false}))
app.post('/post', (req, res) => {
let res = req.body
})
(四)cookie-parser
安装cookie-parser模块
npm install cookie-parser --save
使用并配置cookie
const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
app.use(cookieParser())
app.get("/",(req, res) => {
//获取cookie
let name = req.cookies.name
if(name){
res.send(`${name}已登录`)
}else{
res.send('未登录')
}
})
app.get("/login", (req, res) => {
//设置cookie
res.cookie("name", "zhangsan", {maxAge: 1000*60})
//res.cookie传入三个参数 key(String) value(String) options(cookie有关配置)
res.send("登录成功")
})
options中可以设置的属性:
CookieOptions
{
maxAge?:number; //cookie的过期时间
signed?:boolean; //表示是否签名cookie
expires?:Date; //设置一个具体的过期日期
httpOnly?:boolean //设置cookie只读
path:string //设置可以cookie访问的路径
domain?:string; //可以让多个域名共享cookie eg:{domain:".jd.com"}
secure?:boolean; //为true时,cookie在http无效,在https中才有效
encode?:(val:string)=>string;
sameSite?:boolean |'lax'|'strict'|'none'
}
//signed
当signed为true时,访问cookie则用req.signedCookies而不是req.cookis,并且在配置时:
app.use(cookieParser("jiami")) //可以随便输入一个字符串
(五)express-session
当浏览器访问服务器并发送第一次请求时,服务器会创建一个session对象,生成一个类似key,value的键值对,然后将key(cookie)返回到浏览器(客户)端,浏览器下次再访问时,携带key(cookie),找到对应的session(value)
安装express-session模块
npm install express-session --save
配置并使用
const express = require('express')
const session = require('express-session')
const app = express()
//配置session的中间件
app.use(session({
secret: 'this is session', //服务器端生成session的签名 可以随意设置
name: "myname", //修改session对应cookie名称
resave: false, //强制保存session 即使它没有变化
saveUninitialized: true, //强制将未初始化的session存储 resave和saveUninitialized最好配置不然会报错
cookie: { //session基于cookie,可以配置过期时间等设置
maxAge: 1000*60
},
rolling:true //每次访问时,过期时间都会续期
}))
app.get('/', (req, res) => {
//获取session
let result = req.session.name
})
app.get('/login', (req, res) => {
//设置session
req.session.name = "zhangsan"
})
销毁session
//会把所有session都销毁
req.session.cookie.maxAge = 0
//把session中name设置为空,只作用name
req.session.name = ''
//使用destroy
req.session.destroy()
//也可以传入一个回调函数
req.session.destroy(function(){
...
})
(六)multer图片上传
安装multer
npm install multer -save
上传格式
<from action="/profile" mmethods="post" enctype="multipart/from-data">
<input type="file" name="avatar"></input>
</from>
使用并配置
//app.js
const express = require('express')
const multer = require('multer')
const uploadRouter = require('./upload.js')
const app = express()
app.use('/upload', uploadRouter)
//upload.js
const express = require('express')
const multer = require('multer')
const sd = require('silly-datetime') //解析时间戳生成指定日期格式
const path = require('path')
const mkdirp = require('mkdirp') //异步方法 功能:mkdirp("目录名") 若是该目录不存在,则会创建该目录
//使用该方法配置,存储在文件的图片是没有后缀名的
const upload = multer({
dest: 'static/upload' //图片上传的目录
})
//可以使用以下配置
const storage = multer.diskStorage({
//配置上传的目录
destination: async (req, file, cb) => {
//1.获取当前日期
let day = sd.format(new Date(), "YYYYMMDD")
//2.路径拼接
let dir = path.join("static/upload",data)
let result = await mkdirp(dir)
cb(null, result)
},
//修改上传的文件名
filename: (req, file, cb) => {
//1.获取后缀名
let extname = path.extname(file.originalanme)
//2.根据时间戳生成文件名
cb(null, Date.Now()+extname)
}
})
const upload = multer({storage:storage})
const router = express.Router()
//upload.signle('xxx') xxx为input对应的name值
router.post('/profile', upload.signle('avatar'), (req, res) => {
//req.file is then avatar file
})
module.exports = router
//单文件上传
router.post("/profile", upload.signle('avatar'), (req, res) => {
})
//多文件上传,但是input的name值都一样时
router.post("/profile", upload.array('avatar', 12), (req, res) => {
})
eg:
<input type="file" multiple name="avatar"></input>
or
<input type="file" name="avatar"></input>
<input type="file" name="avatar"></input>
//多文件上传,input的name都不同时
let cpupload = upload.fields([{name:"pic1", maxCount:1}, {name:"pic2",maxCount:1}])
router.post("/profile", cpupload, (req, res) => {
})
eg:
<input type="file" name="pic1"></input>
<input type="file" name="pic2"></input>