06-Node.js express使用

154 阅读8分钟

image.png

一、express 介绍

express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:www.expressjs.

com.cn/

简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)

二、express 使用

2.1 express 下载

express 本身是一个 npm 包,所以可以通过 npm 安装

npm init

npm i express

2.2 express 初体验

大家可以按照这个步骤进行操作:

  1. 创建 JS 文件,键入如下代码

// 导入
const express=require('express')
// 创建应用对象
const app=express()
// 创建路由
app.get('/home',(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');

    res.end('Hello express原神启动')
})

// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})
  1. 命令行下执行该脚本
node <文件名>

# 或者

nodemon <文件名>
  1. 然后在浏览器就可以访问 http://127.0.0.1:3000/home 👌

三、express 路由

3.1 什么是路由

官方定义: 路由确定了应用程序如何响应客户端对特定端点的请求

3.2 路由的使用

一个路由的组成有 请求方法 , 路径 和 回调函数 组成

express 中提供了一系列方法,可以很方便的使用路由,使用格式如下:

app.<method>(path,callback)

代码示例:

//导入 express

const express = require('express');

//创建应用对象

const app = express();

//创建 get 路由

app.get('/home', (req, res) => {

res.send('网站首页');

});

//首页路由

app.get('/', (req,res) => {

res.send('我才是真正的首页');

});

//创建 post 路由

app.post('/login', (req, res) => {

res.send('登录成功');

});

//匹配所有的请求方法

app.all('/search', (req, res) => {

res.send('1 秒钟为您找到相关结果约 100,000,000 个');

});
//自定义 404 路由

app.all("*", (req, res) => {

res.send('<h1>404 Not Found</h1>')

});

//监听端口 启动服务

app.listen(3000, () =>{

console.log('服务已经启动, 端口监听为 3000');

})

3.3 获取请求参数

express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式

//导入 express

const express = require('express');

//创建应用对象

const app = express();

//获取请求的路由规则

app.get('/request', (req, res) => {

//1. 获取报文的方式与原生 HTTP 获取方式是兼容的

console.log(req.method);

console.log(req.url);

console.log(req.httpVersion);

console.log(req.headers);

//2. express 独有的获取报文的方式

//获取查询字符串

console.log(req.query); // 『相对重要』

// 获取指定的请求头

console.log(req.get('host'));

res.send('请求报文的获取');

});

//启动服务

app.listen(3000, () => {

console.log('启动成功....')

})

3.4 获取路由参数

路由参数指的是 URL 路径中的参数(数据)

// 导入
const express=require('express')
// 创建应用对象
const app=express()
// 创建路由
app.get('/:id.html',(req,res) => {
    console.log(req.params.id)
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('原神启动')
})

// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

image.png

四、express 响应设置

express 框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式


// 导入
const express=require('express')
// 创建应用对象
const app=express()
// 创建路由
app.get('/response',(req,res) => {
//1. express 中设置响应的方式兼容 HTTP 模块的方式

//res.statusCode = 404;

//res.statusMessage = 'xxx';

//res.setHeader('abc','xyz');

//res.write('响应体');

//res.end('xxx')
 //2. express 的响应方法
    // res.status(500)
    // res.set('aaa','bbb')
    // res.send('你好')

    // 链式调用
    res.status(500).set('abc','deg').send('原神启动')
})

// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})



//3. 其他响应

res.redirect('http://atguigu.com')//重定向

res.download('./package.json');//下载响应

res.json();//响应 JSON

res.sendFile(__dirname + '/home.html') //响应文件内容

五、express 中间件

5.1 什么是中间件

中间件(Middleware)本质是一个回调函数

中间件函数 可以像路由回调一样访问 请求对象(request) , 响应对象(response)

5.2 中间件的作用

中间件的作用 就是 使用函数封装公共操作,简化代码

5.3 中间件的类型

全局中间件

路由中间件

5.3.1 定义全局中间件

每一个请求 到达服务端之后 都会执行全局中间件函数

声明中间件函数

let recordMiddleware = function(request,response,next){

//实现功能代码

//.....

//执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用next)

next();

}

image.png


// 导入
const express=require('express')
const fs=require('fs')
const path=require('path')
// 创建应用对象
const app=express()

// 声明中间件函数
function recordMiddleware(req,res,next){
    let {url,ip}=req
    // 将信息保存在文件中 access.log
    try {
        fs.appendFileSync(path.resolve(__dirname, './access.log'), `${url} ${ip}\r\n`);
      } catch (error) {
        console.error('写入日志文件时出错:', error);
      }
      
    next()
}
app.use(recordMiddleware)
// 创建路由
app.get('/home',(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('原神启动')
})
app.get('/store',(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('圆滑')
})
// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

5.3.3 定义路由中间件

如果 只需要对某一些路由进行功能封装 ,则就需要路由中间件

调用格式如下:

app.get('/路径',`中间件函数`,(request,response)=>{

});

app.get('/路径',`中间件函数1`,`中间件函数2`,(request,response)=>{

});

完整代码

// 导入
const express=require('express')
const fs=require('fs')
const path=require('path')
// 创建应用对象
const app=express()

// 声明中间件
let checkCodeMiddleware=(req,res,next)=>{
    if(req.query.code==='521'){
        next()
    }else{
        res.send('错误')
    }
}

// 创建路由
app.get('/home',(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('原神启动')
})
app.get('/store',checkCodeMiddleware,(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('圆滑')
})
app.get('/setting',checkCodeMiddleware,(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('哈哈哈')
})
// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

5.4 静态资源中间件

express 内置处理静态资源的中间件


// 导入
const express=require('express')

// 创建应用对象
const app=express()

// 静态资源中间件设置
app.use(express.static(__dirname+'/public'))

// 创建路由
app.get('/home',(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('原神启动')
})

// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>测试</h1>
</body>
</html>

页面效果:

image.png

注意事项:

  1. index.html 文件为默认打开的资源
  2. 如果静态资源与路由规则同时匹配,谁先匹配谁就响应
  3. 路由响应动态资源,静态资源中间件响应静态资源

5.5 获取请求体数据 body-parser

express 可以使用 body-parser 包处理请求体

第一步:安装

npm i body-parser

第二步:导入 body-parser 包

const bodyParser = require('body-parser');

第三步:获取中间件函数

//处理 querystring 格式的请求体

let urlParser = bodyParser.urlencoded({extended:false}));

//处理 JSON 格式的请求体

let jsonParser = bodyParser.json();

第四步:设置路由中间件,然后使用 request.body 来获取请求体数据

app.post('/login',urlParser,(req,res) => {
    //获取 用户名和密码
    console.log('req.body  ----->  ', req.body);
    res.send('获取用户数据')
})

获取到的请求体数据:

[Object: null prototype] { username: 'admin', userpass: '123456' }

完整代码:


// 导入
const express=require('express')
const bodyParser = require('body-parser');
// 创建应用对象
const app=express()


//处理 querystring 格式的请求体
let urlParser = bodyParser.urlencoded({extended:false})
//处理 JSON 格式的请求体
let jsonParser = bodyParser.json();
// 创建路由
app.get('/login',(req,res) => {
    res.sendFile(__dirname+'/form.html')
})
app.post('/login',urlParser,(req,res) => {
    //获取 用户名和密码
    console.log('req.body  ----->  ', req.body);
    res.send('获取用户数据')
})

// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

form.index

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录页面</title>
</head>
<body>
    <h2>用户登录</h2>
    <hr>
    <form action="/login" method="post">
    用户名: <input type="text" name="username"><br/>
    密码: <input type="password" name="password"><br/>
    <button>登录</button>
</form>
</body>
</html>   

六、Router

6.1 什么是 Router

express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。

6.2 Router 作用

对路由进行模块化,更好的管理路由

6.3 Router 使用

创建独立的 JS 文件(homeRouter.js)


const express=require('express')


// 创建路由对象
const router=express.Router()


router.get('/home',(req,res) => {
    res.setHeader('content-type','text/html;charset=utf-8');
    res.end('原神启动')
})

module.exports=router

主文件


// 导入
const express=require('express')
const homeRouter=require('./routers/homeRouter')

// 创建应用对象
const app=express()
app.use(homeRouter)


// 创建路由

app.get('/*',(req,res) => {

    res.send('<h2>404</h2>')
})
// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

七、EJS 模板引擎

7.1 什么是模板引擎

模板引擎是分离 用户界面和业务数据 的一种技术

7.2 什么是 EJS

EJS 是一个高效的 Javascript 的模板引擎

官网: ejs.co/

中文站:ejs.bootcss.com/

7.3 EJS 初体验

下载安装EJS

npm i ejs --save

代码示例

//1.引入ejs

const ejs = require('ejs');

//2.定义数据

let person = ['张三','李四','王二麻子'];

//3.ejs解析模板返回结构

//<%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构

let html = ejs.render(‘<%= person.join(",") %>’, {person:person});

//4.输出结果

console.log(html);

命令行下运行

列表渲染

代码:

//1.引入ejs
const fs=require('fs')
const ejs = require('ejs');
//2.定义数据
let xiyou = ['张三','李四','王二麻子'];


let html=fs.readFileSync('./02.西游记.html').toString()
//3.ejs解析模板返回结构
//<%= %> 是ejs解析内容的标记,作用是输出当前表达式的执行结构
let result = ejs.render(html, {xiyou:xiyou});
//4.输出结果
console.log(result);

02.西游记.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <ul> 
        <%xiyou.forEach(item=>{ %>
            <li><%= item %></li>
        <% })%>
    </ul>
</body>
</html>

条件渲染

//1.引入ejs
const fs=require('fs')
const ejs = require('ejs');

let islogin=true


let html=fs.readFileSync('./03.home.html').toString()
let result = ejs.render(html, {islogin:islogin});
//4.输出结果
console.log(result);

03.home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <% if(islogin){%>
    <span>欢迎回来</span>
    <%}else{ %>
    <button>登录</button><button>注册</button>
    <%} %>
</body>
</html>

express框架中使用ejs

//1.引入ejs
const express=require('express')
const ejs = require('ejs');
const path=require('path')


// 创建应用对象
const app=express()

// 1设置模板引擎
app.set('view engine','ejs')

app.set('views',path.resolve(__dirname,'./views'))


app.get('/home',(req,res) => {
    let title='天下'
    res.render('home',{title})
})

// 监听端口,启动服务
app.listen(3000,() => {
    console.log('服务器已经启动了')
})

views/home.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2> <%= title %></h2>
</body>
</html>

使用express框架-generator工具

下载

npm install -g express-generator

创建express -e 01-generator

下载依赖 npm i

npm start运行

图片上传处理文件列子

下载:npm install formidable@v2

routes/index.js
```js
var express = require('express');
var router = express.Router();


// 1.导入
const formidable=require('formidable')
/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});
// 显示网页表单
router.get('/portrait', (req, res)=> {
  res.render('portrait');
});
// 处理文件上传
router.post('/portrait', (req, res) =>{
  // 创建表单对象
  const form = formidable({multiples:true,uploadDir:__dirname+'/../public/images'});
  // 请求报文
  form.parse(req, (err, fields, files) => {
    if (err) {
      next(err);
      return;
    }
    console.log('  fields----->  ',fields );
    console.log('  files----->  ',files );
    let url ='/images/'+files.portrait.newFilename//将来存在数据库里面
    res.send(url)
  });
});



module.exports = router;

views/portrait.ejs

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h2>文件上传</h2>

    <hr>
    <form action="/portrait" method="post" enctype="multipart/form-data">

        用户名: <input type="text" name="username"><br>
        头像:   <input type="file" name="portrait"><br>
        <hr>
        <button>点击提交</button>
    </form>
</body>
</html>