上一篇文章说到,nodejs获取客户端请求需要我们自己去处理请求参数、请求方式等,而在express框架内部集成了很多好用的方法,我们不需要从0开始编写各种处理逻辑,这样可以极大提高我们的开发效率~
 
通过引入 express ,再执行express函数,生成的app对象通过中间件来进行各种操作。
const express = require('express')
const app = express() app.post('/home', (req, res, next)=>{
res.end('hello express')
}) app.listen('8000', ()=>{})

app属性中有get/post/put/delete等等方法来接收不同请求方式的请求数据,这些方法都属于中间件,另外,它还有use方法可以接收所有类型的请求,并且express中的中间件是可以使用多个的,首先匹配第一个符合条件的中间件来处理请求并响应,如果需要执行多个中间件,可通过中间件回调函数中的第三个参数 next,来执行下一个可匹配的中间件。
 
const express = require('express')
const app = express() app.use('/', (req, res, next)=>{
console.log('匹配到了use中间件')
next()
}) app.post('/home', (req, res, next)=>{
console.log('匹配到了post中间件')
res.end('hello express')
}) app.listen('8000', ()=>{
console.log('开启8000端口')
})

 
由于中间件的这个特性,就可以根据不同的请求类型来统一处理数据,常用的请求方式和类型总共有5种,get请求中有两种,分别是 params 和 query 传参。
params 传参的格式类似于 localhost:8000/goods/1,这个数字1就是动态传入的,query传参的格式类似于 localhost:8080/login?name=kiki,在问号后面使用键值对的形式拼接参数。
express的处理方式非常简单,通过回调函数中 req.params 和 req.query即可获取
app.get('/goods/:id', (req, res, next)=>{
console.log(req.url)
console.log(req.params)
res.end('params')
}) app.get('/login', (req, res, next)=>{
console.log(req.url)
console.log(req.query)
res.end('query')
})

 
post请求中还有另外三种常见的请求类型,分别是 json、urlencoded和form-data。
json字符串表示传递的数据是键值对的形式,格式如 { "name": "kiki", password: 666 },urlencode 格式如 name=kiki&password=666,而form-data就是表单提交的形式,通常用于文件上传。
// 获取 json格式的请求参数
app.use(express.json());
// 获取 urlencoded 格式的请求参数
app.use(express.urlencoded({extended: true}));
// 在下一个匹配的post请求里通过 req.body 来获取, 有兼容性问题, 需要express4.16以上 app.post('/login', (req, res, next) => {
console.log(req.body);
res.end("login success");
});
 
表单提交的处理方式会稍微复杂一点,需要安装第三方库 multer 来处理
const express = require('express')
const multer = require('multer')
const app = express()
const upload = multer() // 传递非文件类型时, 使用upload.any(),传递文件类型时 upload.array("file")
app.use('/login', upload.array("file"), (req, res, next)=>{
console.log(req.files)
console.log(req.body)
res.end('form-data')
}) app.listen(8000, () => {
console.log('开启8000端口')
});

 
上图以form-data的形式发送了一个post请求,请求里包括了非文件和文件类型,req.body可以获取非文件信息,通过req.files可以获取文件信息,文件信息的内容以buffer二进制数据的形式获取,可自行对上传的文件进行处理。
 
 
说完了解析参数,再来看看对客户端的请求做出响应,包括设置响应状态码,响应的参数类型,响应的具体内容
app.get('/login', (req, res, next) => {
console.log(req.query);
// 设置响应码
res.status(200);
// 设置响应类型
res.type("application/json");
res.end(JSON.stringify({name: "kiki", age: 16})); // 以上两行可以合并成 res.json({name: "kiki", age: 16});
});

再来看看express稍微复杂一点的用法,当我们通过express提供的接口是 restful类型的时候,同样一个路由地址,可能对应着多种请求方式,如get/post/put/delete。

如果每一种请求方式都写一次,代码变得难阅读和维护,我们此时可以考虑按接口抽取成单独的路由文件,比如统一匹配/user接口,get请求 /user 时获取所有的user信息,get请求/user/id 时获取某个id的user信息,post请求 /user 时新增用户信息,put请求 /user 时修改用户信息,delete请求 /user 时删除用户。
通过express的Router方法创建router对象,定义所有需要的请求方法,最后导出router对象。
const express = require('express')
const router = express.Router() router.get('/', (req, res, next)=>{
res.json([{
name: 'alice', age: 17
},{
name: 'lili', age: 16
}])
}) router.get('/:id', (req, res, next)=>{
res.json({ name: 'alice', age: 17 })
}) router.post('/', (req, res, next)=>{
res.json('post')
}) router.put('/', (req, res, next)=>{
res.json('put')
}) router.delete('/', (req, res, next)=>{
res.json('delete')
}) module.exports = router;

以上为定义的user文件,可以看到以上的路由是不包含/user这个通用的路由的,因为它被定义在了主入口处,主入口文件引入以上的js文件,将导入的router作为中间件传入到use方法中,这样就可以用四种不同的方式调用同一个接口。

const express = require('express')
const userRouter = require('./routers/user')
const app = express() app.use('/user', userRouter) app.listen(8000, ()=>{})

还有一个比较重要的就是处理请求中的错误,在上面的中间件使用过程中,next方法用于执行下一个匹配的中间,括号里是不需要传参数的,而当需要处理错误的时候,就可以在next中传入参数,然后再定义一个公共的处理错误的中间件。 
const express = require('express')
const app = express() const NOT_FIND = 'NOT_FIND'
const TIME_OUT = 'TIME_OUT' app.get('/login', (req, res, next)=>{
next(new Error(NOT_FIND))
}) app.get('/home', (req, ers, next)=>[
next(new Error(TIME_OUT))
]) app.use((error, req, res, next)=>{
console.log('>>>>>>>>>error', error)
let code = 400;
let message = ''
switch(error.message){
case NOT_FIND:
message = '您的信息有误'
break;
case TIME_OUT:
message = '已超时';
break;
default:
break;
}
res.json({
code,
message
})
}) app.listen(8000, ()=>{})
 
以上就是express中关于开启服务的部分,nodejs中的相关知识可以参考这一篇,nodejs中如何使用http创建一个服务,下一篇聊聊Koa开启服务~
 

让nodejs开启服务更简单--express篇的更多相关文章

  1. hydra nodejs 微服务框架简单试用

    hydra 是一个以来redis 的nodejs 微服务框架 安装 需要redis,使用docker 进行运行 redis docker run -d -p 6379:6379 redis 安装yo ...

  2. [翻译]Kafka Streams简介: 让流处理变得更简单

    Introducing Kafka Streams: Stream Processing Made Simple 这是Jay Kreps在三月写的一篇文章,用来介绍Kafka Streams.当时Ka ...

  3. Kafka Streams简介: 让流处理变得更简单

    Introducing Kafka Streams: Stream Processing Made Simple 这是Jay Kreps在三月写的一篇文章,用来介绍Kafka Streams.当时Ka ...

  4. spring 第一篇(1-1):让java开发变得更简单(下)

    切面(aspects)应用 DI能够让你的软件组件间保持松耦合,而面向切面编程(AOP)能够让你捕获到在整个应用中可重用的组件功能.在软件系统中,AOP通常被定义为提升关注点分离的一个技术.系统由很多 ...

  5. spring 第一篇(1-1):让java开发变得更简单(下)转

    spring 第一篇(1-1):让java开发变得更简单(下) 这个波主虽然只发了几篇,但是写的很好 上面一篇文章写的很好,其中提及到了Spring的jdbcTemplate,templet方式我之前 ...

  6. nodejs学习--express篇

    express篇:http://www.runoob.com/nodejs/nodejs-express-framework.html Express 提供了内置的中间件 express.static ...

  7. 微服务平台(Micro Service Platform : MSP)旨在提供一个集开发、测试、运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效。

    微服务平台(Micro Service Platform : MSP)旨在提供一个集开发.测试.运维于一体的开发者专属平台,让开发者能快速构建或使用微服务,让开发更简单,让运维更高效. MSP采用业界 ...

  8. Anno 让微服务、混合编程更简单(Net love Java)

    在社区或者QQ群我们经常看到有人争辩编程语言的好坏,只要一提起这个话题常常就能引来很多人参与,往往最后就变成了一群人几个小时的骂战.今天我们要说的是如何让Java和.Net(甚至更多语言)相结合.充分 ...

  9. 让服务调用更简单 - Caller.HttpClient

    前言 绝大多数项目都离不开服务调用,服务的调用方式通常是基于Http.RPC协议的调用,需要获取到对应服务的域名或者ip地址以及详细的控制器方法后才能进行调用,如果项目需要支持分布式部署,则需要借助服 ...

  10. 分布式系统的消息&服务模式简单总结

    分布式系统的消息&服务模式简单总结 在一个分布式系统中,有各种消息的处理,有各种服务模式,有同步异步,有高并发问题甚至应对高并发问题的Actor编程模型,本文尝试对这些问题做一个简单思考和总结 ...

随机推荐

  1. PCI-5565系列反射内存卡 反射内存交换机

    主要性能:1路发射,一路接收光纤高速网络2.125GHz.最大256个节点.在板128MByte SDRAM.光纤通讯协议不占用CPU资源.动态包长,每个包4 到 64 个字节.33MHz PCI 3 ...

  2. 2022-11-17:组合两个表。请写出sql语句,执行结果是{“headers“: [“first_name“, “last_name“, “city“, “state“], “values“: [

    2022-11-17:组合两个表.请写出sql语句,执行结果是{"headers": ["first_name", "last_name", ...

  3. 2020-08-11:一颗现代处理器,每秒大概可以执行多少条简单的MOV指令,有哪些主要的影响因素?

    福哥答案2020-08-11: [知乎答案](https://www.zhihu.com/question/413389230)MOV 指令将源操作数复制到目的操作数,是最基本的指令.首先就和CPU主 ...

  4. 2022-01-24:K 距离间隔重排字符串。 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k。 所有输入的字符串

    2022-01-24:K 距离间隔重排字符串. 给你一个非空的字符串 s 和一个整数 k,你要将这个字符串中的字母进行重新排列,使得重排后的字符串中相同字母的位置间隔距离至少为 k. 所有输入的字符串 ...

  5. mysql报错Unknown collation: utf8mb4_0900_ai_ci

    mysql报错Unknown collation: utf8mb4_0900_ai_ci 解决方案: 将文件内的所有 utf8mb4_0900_ai_ci 换成 utf8_general_ci utf ...

  6. 为什么 HashMap 会死循环?

    HashMap 死循环发生在 JDK 1.8 之前的版本中,它是指在并发环境下,因为多个线程同时进行 put 操作,导致链表形成环形数据结构,一旦形成环形数据结构,在 get(key) 的时候就会产生 ...

  7. Linux 下 R 源码安装指南

    本文章同步自作者的语雀知识库,请点击这里阅读原文. 如果你使用的 Linux 系统 GCC 版本太低, 又没有 root 权限 (即使有 root 权限又担心升级 GCC 带来的风险) ; 同时你又不 ...

  8. BGP 反射器;BGP联盟

    目录 BGP反射器 实验拓扑 实验需求 实验步骤 在R2上查看BGP邻居表 在R2上做反射器 在R3上查看1.1.1.1 路由表,进行观察 在R3上查看1.1.1.1 路由详细信息 BGP联盟实验 实 ...

  9. Java 实战介绍 Cookie 和 Session 的区别

    HTTP 是一种不保存状态的协议,即无状态协议,HTTP 协议不会保存请求和响应之间的通信状态,协议对于发送过的请求和响应都不会做持久化处理. 无状态协议减少了对服务压力,如果一个服务器需要处理百万级 ...

  10. 300行代码模拟cdn

    这一生听过许多道理,但还是过不好这一生,这是因为缺少真正的动手实践,光听道理,缺少动手实践的过程,学习难免会让人觉得味同嚼蜡,所以我的分享都比较倾向于实践,在一次次动手实践的过程中感受知识原本纯真的模 ...