nodejs进阶(3)—路由处理
1. url.parse(url)解析
该方法将一个URL字符串转换成对象并返回。
url.parse(urlStr, [parseQueryString], [slashesDenoteHost])
接收参数:
urlStr url字符串
parseQueryString 为true时将使用查询模块分析查询字符串,默认为false
我们通过解析HTTP请求,从中提取出请求的URL以及GET/POST参数。url是nodejs内置的一个模板,我们需要require("url")获取,下面的url:http://localhost:8888/start?foo=bar&hello=world,通过url.parse解析出的一个对象的各个字段名对应url的各部分。
var url = require('url'); var queryUrl = "http://localhost:8888/start?foo=bar&hello=world" ; console.log(typeof url.parse(queryUrl)) ; console.log(url.parse(queryUrl)) ; //输出结果如下: /* object // typeof { protocol: 'http:', slashes: true, auth: null, host: 'localhost:8888', port: '8888', hostname: 'localhost', hash: null, search: '?foo=bar&hello=world', query: 'foo=bar&hello=world', pathname: '/start', path: '/start?foo=bar&hello=world', href: 'http://localhost:8888/start?foo=bar&hello=world' } 加以说明如下: protocol: 请求协议 host: URL主机名已全部转换成小写, 包括端口信息 auth:URL中身份验证信息部分 hostname:主机的主机名部分, 已转换成小写 port: 主机的端口号部分 pathname: URL的路径部分,位于主机名之后请求查询之前 search: URL 的“查询字符串”部分,包括开头的问号。 path: pathname 和 search 连在一起。 query: 查询字符串中的参数部分(问号后面部分字符串),或者使用 querystring.parse() 解析后返回的对象。 hash: URL 的 “#” 后面部分(包括 # 符号) */
用下面的图更形象的描述说明给大家:
url.parse(string).query | url.parse(string).pathname | | | | | ------ ------------------- http://localhost:8888/start?foo=bar&hello=world --- ----- | | | | querystring(string)["foo"] | | querystring(string)["hello"]
2. 路由选择实现代码
处理不同的HTTP请求在我们的代码中是另外一个不同的部分,叫做“路由选择”。
那么,我们接下来就创造一个叫做 路由 的模块吧。
新建属于服务器端的路由文件router.js
1 //-----------------router.js-------------------------------- 2 module.exports={ 3 login:function(req,res){ 4 res.write("我是login方法"); 5 }, 6 register:function(req,res){ 7 res.write("我是注册方法"); 8 } 9 }
服务端调用路由,方式和上一节课《nodejs进阶2--函数模块调用》中最后提到的字符串调用函数一样。
1 //---------4_router.js----------- 2 var http = require('http'); 3 var url = require('url'); 4 var router = require('./router'); 5 http.createServer(function (request, response) { 6 response.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}); 7 if(request.url!=="/favicon.ico"){ 8 var pathname = url.parse(request.url).pathname;//得到请求的路径 9 console.log(pathname); 10 pathname = pathname.replace(/\//, '');//替换掉前面的/ 11 console.log(pathname); 12 router[pathname](request,response); 13 response.end(''); 14 } 15 }).listen(8000); 16 console.log('Server running at http://127.0.0.1:8000/');
上面我们用到了node自带模块url。url.path(urlStr):将一个URL字符串转换成对象并返回。
3. 向页面输出html文件
对于一般的get请求,例如localhost/login 我们需要给浏览器输出个页面login.html,那我们怎么做呢?
首先我们新增两个页面
1.login.html
1 <html> 2 <head> 3 </head> 4 <body> 5 登录: 6 <p>这是一个段落</p> 7 <h1>样式1</h1> 8 </body> 9 <html>
2.register.html
1 <html> 2 <head> 3 </head> 4 <body> 5 注册: 6 <p>这是一个段落</p> 7 <h1>样式1</h1> 8 </body> 9 <html>
读取文件的方法,我们放到文件models/file.js里
1 //-------------models/file.js------------------------- 2 var fs= require('fs'); 3 module.exports={ 4 readfile:function(path,callback){ //异步读文件,需要传入回调函数 5 fs.readFile(path, function (err, data) { 6 if (err) { 7 console.log(err); 8 }else{ 9 callback(data); 10 } 11 }); 12 console.log("异步方法执行完毕"); 13 }, 14 readfileSync:function(path){ //同步读取 15 var data = fs.readFileSync(path,'utf-8'); 16 console.log("同步方法执行完毕"); 17 return data; 18 } 19 }
router.js需要调用文件读取方法,把两个页面html文件读取出内容并输出到response。需要注意的是:res.end()这句话的位置,如果用异步读文件的方法就不能放到server创建那块了
1 //-----------------router.js-------------------------------- 2 var file = require('./models/file'); 3 module.exports={ 4 login:function(req,res){ 5 var callback=function(data){ 6 res.write(data); 7 res.end(); 8 } 9 file.readfile('./views/login.html',callback);//使用异步读取 10 }, 11 register:function(req,res){ 12 var data=file.readfileSync('./views/register.html');//使用同步读取 13 res.write(data); 14 res.end(); 15 } 16 }
我们重新运行:node 4_router.js。分别在浏览器输入http://localhost:8000/login 和http://localhost:8000/register ,输出了login.html和register.html页面的内容。