1.http概述
开发接口(不用任何框架)
- Nodejs处理http请求;
- 搭建开发环境;
- 开发接口(暂时不连接数据库,不考虑登录问题)
- http请求概述
- DNS解析,建立TCP连接,发送http请求
- server 接收到http请求,处理,并返回
- 客户端接收到返回数据,处理数据(如渲染页面,执行js )
我们可以查看控制台中的 Headers,里面有请求的各种信息。 首先是 remote address,这个就是对应 DNS 解析,将例如百度解析成这里面的地址(443 是 https 默认端口)。然后建立 TCP 连接也就是所谓的三次握手(客户端问服务器说可用;服务端告客户端说可用;客户端告知服务端接下来要用)。
2.处理get请求
querystring 就是 get 传的参数,postdata 就是 post 传的参数, 路由就是所谓的地址。
nodejs处理http请求
- get请求和querystring
- post请求和postdata
- 路由
const http = require( 'http ' ); const server = http.createServer((req,res)=→>{ res.end( ' hello world ' ); }); server.listen(8000); //然后浏览器访问http://localhost: 8000/
上面这个就是最基本的示例,都是按照这个结构来处理请求。
nodejs处理get请求
- get 请求,即客户端要向server端获取数据,如查询博客列表;
- 通过querystring 来传递数据,如a.html?a=100&b=200;
- 浏览器直接访问,就发送get请求
Nodejs处理get请求:
const http = require( 'http' ); const querystring = require( 'querystring' ); const server = http.createServer((req,res) => { console.log(req.method) // GET const url = req.url1/获取请求的完整url req.query = querystring.parse(url.split( '?')[1]) //解析querystring res.end ( JSON.stringify(req.query));//将querystring返回 }); server.listen ( 8000);
接下来实例演示一下,新建一个 http-test 文件夹,npm 初始化一下,创建一个 app.js;
const http = require('http') const querystring = require('querystring') const server = http.createServer((req,res)=>{ console.log('method:',req.method)//GET const url = req.url console.log( 'url:',url) req.query = querystring.parse(url.split( '?')[1]) console. log('query:', req.query) res.end( JSON.stringify( req.query) ) }) server.listen(8000) console.log( 'OK')
3.nodejs处理post请求
- post请求,即客户端要像服务端传递数据,如新建博客
- 通过post data传递数据,后面会演示
- 浏览器无法直接模拟,需要手写js ,或者使用postman
js 手写 ajax 去进行 post 请求,但是这个比较麻烦,还需要考虑到跨域什么的。故推荐使用 postman 。 搜索 postman chrome crx 可得该插件,安装完成在 chrome 中输入 chrome : //apps 就可以选择该插件,点击即可进入。
const http = require('http') const server = http.createServer((req, res) => { if ( req.method === 'POST') { //数据格式 console. log( ' content-type', req . headers ['content-type' ]) //接收数据 let postData = "" req.on( 'data', chunk => { postData += chunk. toString() req.on('end', () => { console. log( postData ) res.end( 'hello world') //在这里返回,因为是异步 }) } }); | server. listen(8000) ;
这里为什么监听 data ,当然是为了获取数据,注意它就像一个管子连接客户端和服务端,负责传传输数据,一点点传(有时候传的数据少可能就一次就执行完成,数据多可能会多次执行该事件,随时来数据随时触发),毕竟不可能一下子就接收这么多数据什么的,这样子流动才比较合理,接收完成才触发 end 事件。(服务端接收 post 数据都是如此)那么怎么使用 postman 发送 post 请求?这个简单,只需要切换成 post ,输入 node 监听的网址,选择 body ,选择 raw (旁边有显示 json ,这就是为什么请求头的 content-type 是 json格式,因为是自己设置嘛),往里面写点 json 数据即可。
nodejs处理路由:
路由就是 url/资源的唯一标识,/xxx 什么的.
const http = require( 'http ' ); const server = http.createServer((req,res) => { const url = req.url const path = url.split( '?')[0] res.end( path);//返回路由 }); server.listen(8000 );
4.处理http请求的综合实例
首先获取各个信息,设置返回格式(都是字符串但是有各种格式像 json、html 等等。这个返回格式决定了返回的那一坨信 息 是 什 么 东 西 ,可 能 是 json 数 据 , 可 能 是 html 即 text/html),再定义返回的数据集上面拿到的数据。 返回的是 GET 则直接返回数据即可,是 POST 则还需要postData 去搞一下。
5.搭建开发环境
- 从0开始搭建,不适用任何框架
- 使用nodemon监测文件变化,自动重启node
- 使用cross-env设置环境变量,兼容mac linux和windows
app.js 里面主要是为了业务配合,做一些配置(返回格式什么解析 xxx)和基本的 sever 没有关系,是一些底层的代码。 www.js 则是与 server 有关系的基本的功能(目前就是一个 port)分开刚好相互引用是为模块化!其实很简单,安装 cross-env 和 nodemon,同时配置 dev 和prd 两个不同的环境即可.然后 app.js 写一个通用的业务逻辑代码(就是起一个服务里面的东西,方便用)。
建一个 www.js 负责基本的框架就是一个大概的结构:
6.初始化路由
开发接口:
- 初始化路由:根据之前技术方案的设计,做出路由
- 返回假数据:将路由和数据处理分离,以符合设计原则
根据之前的接口设计,我们大概需要设计两个文件对应 5 和 1 个接口,方法的话只有 get 和 post 。 好,先来做路由,环境变量和设置返回格式(后端返回 json 比较友好)可以留下,其它删了。建一个 src 文件夹,所有的内容都写到这个文件夹,下面再建一个 router 文件夹,分 别建两个文件 blog.js (5 个接口)和 user.js (1 个接口)。 先写 blog.js 里面写一个函数里面写各个接口测试一下,将该 函数返回,回到 user.js ,也建一个函数,只需要登录接口, 最后输出出去即可。 回到 app.js 引用这两个文件,将函数返回的对象变成字符串再发送出去,需要考虑命中其中一个路由或者都不命中的情况。
app.js 本来就只是一个入口文件,不适合做大量的处理,故我们分成好两个文件对应不同的路由,只需要引用然后发送即可。 我们注意到获取 path 和 url 写了多处,我们就可以把这个重 复的代码放到 app.js 中,并且用 req.path 保存起来,以后其他文件使用的话只需要 req.path 即可使用 path 。
7.开发路由
在搞之前我们可以先建一个数据模型(以后用的到),故建 一个 model 文件夹下面建一个 resModel.js ,这个建一个基类 BaseModel 。
为什么需要判断是不是字符串?这个是为了兼容只传一个参数且还是传的字符串(则直接让字符串指向这个参数,因为没有对象嘛,本来这个参数该是对象而缺了一个字符串参 数,那就木有对象,只有字符串),正常应该一个对象加一个字符串。然后再根据对象的设置成对象,字符串数组成字符串(只传一个由于是 null 就不会走这个分支)。
再建一个 SuccessModel 继承基类,加多一个 errno=0 ,再建一个 ErrorModel 继承基类将 errno 设置为 -1.这里就是为了让外面接口返回数据的话能有一个格式(比较 清楚是成功失败)方便统一。 接下来继续写路由,所有公共的函数什么的都可以写在app.js,这个呃,要具体处理路由自然是需要拿到 query ,所以我们就来解析这个 query (按之前所写)。
解析完成后我们在 src 再建一个 controller 文件夹,下面建一个 blog.js ,建立一个函数 getList 需要两个参数 author 和 keyword,我们可以返回一个假数据(对象数组),但是格式要对,最后回整个函数(假装使用了这两个参数)。 那么我们就可以在 router 里面拿到这个函数了,当然想要先 从 query 拿到两个参数再传给函数,函数的结果给 listData ,接下来就需要 model 了,引用两个 model ,把 listData 传给成功 model 即可。
那么为什么还要分一个 controller 分出来?我们可以先看看外面目前分了几层。第一层自然是 www.js (大体框架结构)然后是 app.js (基本设置)接着是 router (涉及部分逻辑返回一个正确的格式,怎么处理这个格式不管)然后就是controller 了(这个是最关心数据的了)。
很简单嘛,首先肯定是回到 controller 定义一个 getDetail 的 函数,返回一个假数据,导出函数即可。 回到 router 下面引入这个函数,先获取 id,再调用这个函数,传入 id,再将结果传给成功model。 好了,GET 请求就开发完成了,接下来搞 POST,POST 自然是最需要处理 postData,而处理的话我们是通过 on 方法,但是由于全员异步,我们就得利用 promise,不然实在费劲。
那需要理解一下 promise ,我们建一个测试文件夹改文件夹下面有一个 index.js 还有一个 files 文件夹,文件夹里面有 3 个 json ,分别有 next 属性指向下一个 json (最后一个就是 null),需求是这样子的,根据 next 一个个读取文件。读取文件的话 node 中需要引入 fs 模块(文件操作) path模块(操作文件路径)。我们可以利用 path 的 resolve 方法来拼接路径,__dirname 代表当前文件目录(node.js 的全局变量,直接用即可),下一个参数代表当前文件在哪个地方下面,下一个参数代表我们具体要的文件名如此就能组成要的文件的绝对路径。再利用 readFile 方法,传入拿到的路径就可以拿到这个文件(异步),另外有两个参数 err 和 data 。发现可以拿到文件之后我们整合成一个函数,先用 callback ,基本就是刚才那个东西,不过传给回调之前,可以先变成字符串再变成 json 格式再传。层层打印三个 json 。回调地狱,用 promise 试一下,这个就不需要传回调函数了。
9.开发路由(处理Postdata)
既然会了 promise ,那么就可以来处理 postData ,回到 app.js ,建一个 getPostData 函数,如果不是 POST 请求则直接返回一个空就行,同样的不是 json 格式也返回个空。 那么继续,往下获取 postData ,获取完还要判断是不是空的, 是则继续返回空,不是则返回 postData ,另外呃我们注意到 并没有使用 reject ,这个是因为我们认为这些不是错误,只是各自情况,故返回空而不是错误! 那么怎么执行?在处理路由之前执行,同时塞到 req.body 里面,再把处理路由的部分塞到这里,如此就可以在处理路由里面使用这个 postData 。
10.开发路由(新建和更新)
既然我们已经拿到 postData ,那么就可以把 req.body 赋值给 blogData。 回到 controller 建一个 newBlog 函数,需要传入 blogData (默认为空对象),需要返回一个 id (表示插入数据库的 id )。 引入这个函数,在 router 中使用。 接下来就是更新路由,获取 id (由于这里也需要获取 id ,所以我们可以写到最上面就只需要写一次到处可以引用)。回到 controller 新建一个 updateBlog 函数,返回 true 表示更新成功即可。回到 router 引用,根据返回的布尔值决定操作是否成功选择不同的 model 。
if (method =-=:'POST' && req.path ame ' /api/blog/new ')圈 const data = newBlog(req.body) return new SuccessModel(data) } if (method == 'POST:&& req. path === '/ api/blog/update') { const result = updateBlog(id,req.body) if(result){ return new SuccessnModel(result)} else { return new ErrorModel('博客失败')) }
11.开发路由(删除路由和登录路由)
删除的话只需要接收一个 id 即可,返回一个布尔值,回到router,把 id 传过去就行,依然判断是否存在传不同的 model 。 接下来就是负责登录路由,这个的话我们在 controller 下面 建一个 user.js ,在这里处理具体的数据,定义一个 loginCheck 函数,接收参数 username 和 password 。回到 router ,获取名称和密码自然是从 req.body 获取,因为 postData 都是存在这里的。根据返回的布尔值返回不同的model。
总结:
- nodejs处理http请求的常用技能,postman的使用
- nodejs开发博客项目的接口(未连接数据库,未使用登录)
- 为何要将router 和controller 分开?
const { loginCheck } = require('../controller/user') const { successModel,ErrorModel } = require('../model/resModel') const handleUserRouter = (req,res) => { const method = req.method if(method == "POST' && req.path === '/api/user/login ') { const { username,password } = req.body const result = logincheck(username,password) if (result){ return new SuccessModel() }else{ return new Errormodel('登录失败') } } } module.exports = handleUserRouter //这里是定义user的路由