Express框架
express的使用
- 使用express构建服务
// 1. 导入express
const express = require("express")
// 2.创建应用对象
const app = express();
// 3.创建路由
// Get
app.get("/login",(req,res)=>{
res.end("hello express")
})
// 4. 监听端口,启动服务
app.listen(3000,()=>{
console.log("Server Running!");
})
express路由
-
什么是路由
- 路由确定了应用程序响应客户端对特定端点的请求
-
路由的使用
- 一个路由的组成由 请求方法\路径\回调函数组成
- express提供一系列的方法使用路由: == app.(path,callback) ==
// Get
app.get("/login",(req,res)=>{
res.end("hello express")
})
// All url
app.get("/",(req,res)=>{
res.end("This is home")
})
// Post
app.post("/update",(req,res)=>{
res.end("Post update Success")
})
// All methods
app.all("/home",(req,res)=>{
res.end("home index")
})
// All
app.all("*",(req,res)=>{
res.end("404 Not Found!")
})
express处理请求
- 获取请求参数
app.get("/request", (req, res) => {
// 原生node操作
console.log(req.method);
console.log(req.url);
console.log(req.httpVersion);
console.log(req.headers);
// express操作
console.log(req.path); // 获取请求路径
console.log(req.query); // 获取请求参数
console.log(req.ip); // 获取客户端的ip
const host = req.get("host") // 获取请求头
res.end("hello express")
})
- 获取路由参数
app.get("/goods/:id", (req, res) => {
// 获取路由参数
const id = req.params.id
console.log(id, "id");
res.end("hello express")
})
- 设置响应
app.get("/response", (req, res) => {
// 原生node响应
res.statusCode=404
res.statusMessage="Not Found"
res.setHeader("server","nodejs/express")
res.write("Hello Response!")
res.end("express response")
// 框架express响应
res.status(500)
res.set("express-header","exx")
res.send("你好 Express") // 内置做了字符集的转换
// 支持链式操作
res.status(500).set('exx','555').send("656666")
})
- 其他的响应设置
//创建路由
app.get("/other", (req, res) => {
// 跳转响应--重定向
res.redirect("https://baidu.com")
// 下载响应
res.download(__dirname + "/package.json")
// JSON响应
res.json({
name: "other",
mes: "this is response msg!"
})
// 响应文件内容
res.sendFile(__dirname + "/index.js")
})
express中间件
-
什么是中间件
- 本质上是一个回调函数
- 中间件可以像路由回调一样访问 请求对象 \ 响应对象
- 作用就是使用函数封装公共函数
-
中间件的类型
- 全局中间件
- 路由中间件
-
全局中间件实践
- 记录访问的ip和url
//导入express
const express = require("express")
const fs = require("fs")
const path = require("path")
const app = express();
//创建路由
app.get("/home", (req, res) => {
// 获取url 和 ip
let { url, ip } = req
// 将信息保存到文件ip.log之中
fs.appendFileSync(path.resolve(__dirname, "./ip.log"), `${ip} ==> ${url}\r\n`)
res.end("Express Response")
})
//监听端口,启动服务
app.listen(3000, () => {
console.log("Server Running!");
})
- 重复的操作封装成全局中间件
/* 创建一个记录url和ip的全局中间件 */
function recordMiddleware(req, res, next) {
// 获取url 和 ip
let { url, ip } = req
// 将信息保存到文件ip.log之中
fs.appendFileSync(path.resolve(__dirname, "./ip.log"), `${ip} ==> ${url}\r\n`)
// 调用next
next();
}
// 使用中间件
app.use(recordMiddleware);
//创建路由
app.get("/home", (req, res) => {
res.end("Express Response home")
})
app.get("/my", (req, res) => {
res.end("Express Response my")
})
::ffff:127.0.0.1 ==> /home
::ffff:127.0.0.1 ==> /home
::ffff:127.0.0.1 ==> /my
- 路由中间件的实践
- 路由中间件
// 声明一个中间件函数
let checkCodeMiddleware = (req, res, next) => {
// 判断url之中是否有code参数等于666
if (req.query.code === "666") {
next();
} else {
res.send("口令错误==>Error !")
}
}
// 在路由之中 传入中间件函数进行url的校验
app.get("/home", checkCodeMiddleware, (req, res) => {
res.send("my Home !")
})
app.get("/about", checkCodeMiddleware, (req, res) => {
res.end("Express Response about")
})
app.get("/setting", checkCodeMiddleware, (req, res) => {
res.end("Express Response setting")
})
- 静态资源中间件
- 使用
// 静态资源中间件
// 自动设置MiMe类型,并且读取文件内容
app.use(express.static(__dirname + "/public"))
- 注意事项 - index.html 为默认打开的资源 - 如果静态资源与路由规则同时匹配的,谁先匹配谁就响应 - 路由响应动态的资源,静态资源中间件响应静态资源
express获取请求体数据
- 使用插件body-parser中间件
//导入express
const express = require("express")
const bodyParser = require("body-parser")
const app = express();
// 解析json对象的中间件
const jsonParser = bodyParser.json();
// 解析queryString格式的中间件
const urlencodedParser = bodyParser.urlencoded({ extended: false })
//创建路由
app.get("/login", (req, res) => {
// 响应html内容
res.sendFile(__dirname + "/public/index.html")
})
app.post("/login",urlencodedParser, (req, res) => {
console.log(req.body); // [Object: null prototype] { username: 'admin', psd: '894515' }
res.send("登录成功!!")
})
//监听端口,启动服务
app.listen(3000, () => {
console.log("Server Running!");
})
express防盗链
- 使用referer实现图片的防盗链
// 声明中间件
app.use((req, res, next) => {
// 检测请求头之中的referer
let referer = req.get("referer")
console.log(referer);
if (referer) {
// 实例化
let url = new URL(referer)
// 获取
let hostname = url.hostname
if (hostname !== "127.0.0.1") {
res.status(404).send("404 NOT FOUND !")
return;
}
}
next()
})
express的路由模块化
- 路由模块文件
// 1. 导入express
const express = require("express")
// 2.创建路由对象
const router = express.Router();
// 3. 创建路由规则
// 创建路由
router.get("/home", (req, res) => {
res.send("首页!!")
})
router.get("/search", (req, res) => {
res.send("搜索!!")
})
router.get("/mine", (req, res) => {
res.send("我的!!")
})
// 4. 导出router对象
module.exports = router
- index.js主文件
/* 导入router */
const HomeRouter = require("./routes/homeRouter")
const AdminRouter = require("./routes/adminRouter")
// 设置使用
app.use(HomeRouter);
app.use(AdminRouter);
EJS模板引擎
-
什么是模板引擎
- 模板引擎是分离用户界面和业务数据的一种技术
-
ejs是什么
-
ejs的初步使用体验
- <%= 变量 %>
// 1. npm安装ejs
// 2. 导入ejs
const ejs = require("ejs");
// 字符串
let num = 26;
let str = `我今年${num}`;
console.log(str);
// 使用ejs进行渲染
// 第一步
let result = ejs.render(`我今年有<%= num %>,result`, { num: num });
console.log(result);
// 第二步变量拆分
let temp = `我今年有<%= num %>,result`
let result = ejs.render(temp, { num: num });
console.log(result);
// 第三步文件可拆分
const fs = require("fs")
let temp = fs.readFileSync("./temp.html").toString();
let result = ejs.render(temp, { num: num });
console.log(result);
- ejs的列表渲染
- <% js代码执行环境 %>
const ejs = require("ejs");
let list = [1, 2, 3, 4, 5, 6, 7, 8];
// 1. 列表渲染
let result = ejs.render(`<ul>
<% list.forEach(item=>{%>
<li><%= item%></li>
<%})%>
</ul>`, { list: list });
console.log(result);
// 2. 拆分文件
const fs = require("fs")
let html = fs.readFileSync("./temp2.html").toString();
let result = ejs.render(html, { list: list });
console.log(result);
-
ejs的条件渲染
const ejs = require("ejs");
// 变量
let flag = false;
// 1. ejs实现第一步
let result = ejs.render(`
<% if(flag){ %>
<span>变量为true</span>
<% }else{ %>
<span>变量为false</span>
<% } %>
`, { flag: flag });
console.log(result);
// 2. ejs实现第二步
let fs = require('fs');
let str = fs.readFileSync("./03.html").toString();
let result = ejs.render(str, { flag: flag });
console.log(result);
- express框架之中使用ejs
//导入express
const express = require("express")
const fs = require("fs");
const ejs = require("ejs");
const path = require("path");
// 创建应用对象
const app = express();
/* express框架使用ejs */
// 1.设置模板引擎
app.set("view engine", 'ejs');
// 2.设置模板文件的存放位置
app.set("views", path.resolve(__dirname, "./views"))
app.get("/home",(req,res)=>{
// 3.render响应
// res.render("模板文件名","数据")
let title = "这是express使用ejs";
res.render("home",{title});
// 创建模板文件
// views文件夹之下创建home.ejs(下文)
})
//监听端口,启动服务
app.listen(3000, () => {
console.log("Server Running!");
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>
<%= title %>
</h2>
</body>
</html>
express-generator 工具
- express-generator工具
- 官方提供的生成基础express的框架工具
- npm install -g express-generator
- 安装完成之后暴露一个全局的指令 express
- express -e 文件名称
文件上传
- 文件目录
--project // 项目根目录
--bin
--node_modules
--public // 静态资源存储位置,项目根文件夹
-images // 根目录存储图片资源文件夹
-javascripts
-stylessheets
--routes // 路由文件
-index.js
-user.js
--views // ejs文件位置
-error.ejs
-form.ejs
-index.ejs
--app.js // 入口文件
--package.json
--package-lock.json
- 上传第一步: 创建用户上传界面
// index.js创建路由
// 文件上传表单页
router.get('/form', function (req, res, next) {
res.render('form');
});
<!-- views文件夹下创建用户上传界面 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h2>表单上传</h2>
<!-- 文件上传的必须属性 enctype -->
<form action="/form" method="post" enctype="multipart/form-data">
姓名: <input type="text" name="username"><br>
头像: <input type="file" name="avatar"><br>
<hr>
<button>点击提交</button>
</form>
</body>
</html>
- 上传文件第二步: 接收用户上传
/* index.js之中定义接口接收处理用户上传文件资源 */
var express = require('express');
var router = express.Router();
// 导入文件处理包(第三方工具包)
const formidable = require("formidable");
// 文件上传处理接口
router.post('/form', function (req, res, next) {
res.setHeader('content-type', 'text/html;charset=utf8')
// 1. 设置 表单对象
const form = formidable({
multiples: true,
uploadDir: __dirname + "/../public/images", // 存储位置
keepExtensions: true // 保持文件的后缀名
})
// 2. 解析请求报文
// err 错误信息 fields 包含非文件的数据 files 文件数据
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
console.log(fields, files)
// 3. 保存文件 (通过配置进行保存)
// 4. 保存文件的路径,用于之后用户的访问
let avatar_url = "/images/"+files.avatar.newFilename; // 将来存储于数据库
// 5.响应
res.send(avatar_url)
// res.send("OK")
});
// res.end("成功!")
});
module.exports = router;