Nodejs入门--Express框架

60 阅读6分钟

Express框架

express的使用

  1. 使用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路由

  1. 什么是路由

    • 路由确定了应用程序响应客户端对特定端点的请求
  2. 路由的使用

    • 一个路由的组成由 请求方法\路径\回调函数组成
    • 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处理请求

  1. 获取请求参数
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")
})


  1. 获取路由参数
app.get("/goods/:id", (req, res) => {
    // 获取路由参数
    const id = req.params.id
    console.log(id, "id");

    res.end("hello express")
})


  1. 设置响应
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")

})

  1. 其他的响应设置
//创建路由
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中间件

  1. 什么是中间件

    • 本质上是一个回调函数
    • 中间件可以像路由回调一样访问 请求对象 \ 响应对象
    • 作用就是使用函数封装公共函数
  2. 中间件的类型

    • 全局中间件
    • 路由中间件
  3. 全局中间件实践

  • 记录访问的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

  1. 路由中间件的实践
  • 路由中间件
// 声明一个中间件函数
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")
})

  1. 静态资源中间件
  • 使用
// 静态资源中间件
// 自动设置MiMe类型,并且读取文件内容
app.use(express.static(__dirname + "/public"))

  • 注意事项 - index.html 为默认打开的资源 - 如果静态资源与路由规则同时匹配的,谁先匹配谁就响应 - 路由响应动态的资源,静态资源中间件响应静态资源

express获取请求体数据

  1. 使用插件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防盗链

  1. 使用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. 路由模块文件
// 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

  1. index.js主文件

/* 导入router */
const HomeRouter = require("./routes/homeRouter")
const AdminRouter = require("./routes/adminRouter")
// 设置使用
app.use(HomeRouter);
app.use(AdminRouter);

EJS模板引擎

  1. 什么是模板引擎

    • 模板引擎是分离用户界面和业务数据的一种技术
  2. ejs是什么

  3. 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);

  1. 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);



  1. 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);

  1. 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 工具

  1. express-generator工具
    • 官方提供的生成基础express的框架工具
    • npm install -g express-generator
    • 安装完成之后暴露一个全局的指令 express
    • express -e 文件名称

文件上传

  1. 文件目录
 --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
  1. 上传第一步: 创建用户上传界面
// 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>
  1. 上传文件第二步: 接收用户上传

/* 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;