​Node.js系列七 - express开发web服务器

2021-02-07  本文已影响0人  懂会悟

1、 Express初体验

1.1. express的安装

express的使用过程有两种方式:

方式一:

npm install -g express-generator
express express-demo
// 项目目录结构
├── 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
node bin/www

方式二:从零学习搭建

上面创建的项目express项目,很多内容可能我们并不认识,所以刚开始我们最好从零来学习。

npm init -y
npm install express

1.2. express初体验

const express = require('express');

// 创建服务器
const app = express();

// /home的get请求处理
app.get("/home", (req, res) => {
  res.end("Hello Home");
});

// /login的post请求处理
app.post("/login", (req, res) => {
  res.end("Hello Login");
});

// 开启监听
app.listen(8000, () => {
  console.log("服务器启动成功~");
})

1.3. 请求和响应

const express = require('express');

const app = express();

app.get('/users/:userId', (req, res, next) => {
  console.log(req.params.userId);
  res.json({username: "Tom", level: 99});
});

app.listen(8000, () => {
  console.log("静态服务器启动成功~");
})


2、Express中间件

2.1. 认识中间件

Express是一个路由和中间件的Web框架,它本身的功能非常少:

中间件是什么呢?

中间件中可以执行哪些任务呢?

如果当前中间件功能没有结束 ==请求-响应周期==,则必须调用next()将控制权传递给下一个中间件功能,否则,请求将被挂起。

2.2. 应用中间件

那么,如何将一个中间件应用到我们的应用程序中呢?

我们先来学习use的用法,因为methods的方式本质是use的特殊情况;

最普通的中间件

之所以称之为最普通的中间件,是因为无论是什么path、methods都会应用该中间件;

const express = require('express');

const app = express();

app.use((req, res, next) => {
  console.log("common middleware 01");
  next();
})

app.use((req, res, next) => {
  console.log("common middleware 02");
  res.end("Hello Common Middleware~");
})

app.listen(8000, () => {
  console.log("中间件服务器启动成功~");
})

中间件的执行顺序:

path匹配中间件

如果我们希望匹配一个明确的路径,也可以使用use方法:

// 路径匹配中间件
app.use('/home', (req, res, next) => {
  console.log("home middleware 01");
  next();
});

app.use('/home', (req, res, next) => {
  console.log("home middleware 02");
  next();
  res.end("Hello Home middleware");
});

app.use((req, res, next) => {
  console.log("common middleware");
});

path和method匹配中间件

// method匹配中间件
app.get('/home', (req, res, next) => {
  console.log("home get middleware");
  next();
})

app.post('/login', (req, res, next) => {
  console.log("login post middleware");
  next();
});

app.use((req, res, next) => {
  console.log("common middleware");
});

注册多个中间件

// 注册多个中间件
const homeMiddleware1 = (req, res, next) => {
  console.log('home middleware 01');
  next();
}

const homeMiddleware2 = (req, res, next) => {
  console.log('home middleware 02');
  next();
}

const homeHandle = (req, res, next) => {
  res.end("Hello Home~");
}

app.get('/home', homeMiddleware1, homeMiddleware2, homeHandle);

2.3. 应用其他中间件

并非所有的中间件都需要我们从零去编写:

request解析中间件

在客户端发送post请求时,会将数据放到body中:

我们这里先使用json传递给服务器body:

不进行解析时的操作:

app.post('/login', (req, res, next) => {
  req.on('data', (data) => {
    console.log(data.toString());
  })
  req.on('end', () => {
    res.end("登录成功~");
  });
});

我们可以使用expres内置的中间件或者使用body-parser来完成:

app.use(express.json());

app.post('/login', (req, res, next) => {
  console.log(req.body);
  res.end("登录成功~");
});

如果我们解析的是 application/x-www-form-urlencoded:

我们可以使用express自带的 urlencoded函数来作为中间件:

app.use(express.json());
app.use(express.urlencoded({extended: true}));

app.post('/login', (req, res, next) => {
  console.log(req.body);
  res.end("登录成功~");
});

日志记录中间件

如果我们希望将请求日志记录下来,那么可以使用express官网开发的第三方库:morgan

npm install morgan

直接作为中间件使用即可:

const loggerWriter = fs.createWriteStream('./log/access.log', {
  flags: 'a+'
})
app.use(morgan('combined', {stream: loggerWriter}));

2.4. 请求和响应

客户端传递到服务器参数的方法常见的是5种:

请求解析

方式一:params

请求地址:http://localhost:8000/login/abc/why

获取参数:

app.use('/login/:id/:name', (req, res, next) => {
  console.log(req.params);
  res.json("请求成功~");
})

方式二:query

请求地址:http://localhost:8000/login?username=why&password=123

获取参数:

app.use('/login', (req, res, next) => {
  console.log(req.query);

  res.json("请求成功~");
})

响应方式

类似于http中的response.end方法,用法是一致的

res.end("Hello World");

json方法中可以传入很多的类型:object、array、string、boolean、number、null等,它们会被转换成json格式返回;

res.json({name: "why", age: 18});

用于设置状态码:

res.status(204);

3、其他知识的补充

3.1. 路由的使用

如果我们将所有的代码逻辑都写在app中,那么app会变得越来越复杂:

我们可以使用 express.Router来创建一个路由处理程序:

// 用户相关的处理
const userRouter = express.Router();

userRouter.get('/', (req, res, next) => {
  res.end("用户列表");
});

userRouter.post('/', (req, res, next) => {
  res.end("创建用户");
});

userRouter.delete('/', (req, res, next) => {
  res.end("删除用户");
});

app.use('/users', userRouter);

当然,我们可以配置更多的路由,并且将所有的逻辑放到一个单独的文件中。

3.2. 静态资源服务器

部署静态资源我们可以选择很多方式:

const express = require('express');

const app = express();

app.use(express.static('./build'));

app.listen(8000, () => {
  console.log("静态服务器启动成功~");
})

3.3. 错误处理方式

app.use((req, res, next) => {
  next(new Error("USER DOES NOT EXISTS"));
});

app.use((err, req, res, next) => {
  const message = err.message;

  switch (message) {
    case "USER DOES NOT EXISTS":
      res.status(400).json({message})
  }

  res.status(500)
})
上一篇 下一篇

猜你喜欢

热点阅读