nodejs 用http模块搭建的服务器的路由,以及路由代码的重构过程

我们打开浏览器浏览网页时,点击上面不同的模块,地址栏中的路由会发生相应的变化,从而,浏览器向服务器发起请求的内容也会发生改变,那么服务端,是如何来做的呢?

服务端也是,通过路由来做出不同的响应的,我们已经知道,服务器对象的参数有request,和response两个参数。request里就携带了,浏览器请求所携带的值。

request.url返回的是浏览器中路由的值

我们可以根据这个值来判断,服务器需要返回给浏览器什么内容,

下面来看一下server.js的代码:

var http = require("http");
var fs = require("fs");

var startServer = function(){
    var onRequest = function(request,response){
        console.log("request received"+request.url);
        if(request.url==="/"||request.url==="/home"){
            response.writeHead(200,{"Content-Type":"text/html"});
            fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
        }else if(request.url==="/review"){
            response.writeHead(200,{"Content-Type":"text/html"});
            fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
        }else if(request.url==="/api"){
            response.writeHead(200,{"Content-Type":"application/json"});
            var jsonObj={name:"lili",job:"coder",age:18};
            response.end(JSON.stringify(jsonObj));
        }else{
            response.writeHead(200,{"Content-Type":"text/html"});
            fs.createReadStream(__dirname+"/404.html","utf8").pipe(response);
        }
        
    }

    var server = http.createServer(onRequest);
    //最后让服务器监听一个端口
    server.listen(3000,"127.0.0.1");//还可以加第二个参数 127.0.0.1代表的是本地

    console.log("server started on localhost port 3000");//加一个服务器启动起来的提示
}

module.exports.startServer=startServer;

上面server.js中,根据不同的路由,让服务器返回给浏览器不同的内容,当找不到内容时,返回一个404页面

把server.js引入到app.js中

var server = require("./server");

server.startServer();

执行node app

在浏览器中 localhost:3000

后面跟上不同的路由,会显示不同的页面,当匹配不到路由时,会显示404页面!!!

路由重构过程

上面的代码又显的有些臃肿,需要来重构一下,怎么来重构呢?页面中许多路由路径,还有if判断显得有些臃肿,所以就重构它:

先从server.js开始,我们可以将这些if else判断语句注释掉,用一个函数代替

var http = require("http");
var fs = require("fs");

var startServer = function(route){
    var onRequest = function(request,response){
        console.log("request received"+request.url);
        route(request.url);
        // if(request.url==="/"||request.url==="/home"){
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
        // }else if(request.url==="/review"){
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
        // }else if(request.url==="/api"){
        //     response.writeHead(200,{"Content-Type":"application/json"});
        //     var jsonObj={name:"lili",job:"coder",age:18};
        //     response.end(JSON.stringify(jsonObj));
        // }else{
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/404.html","utf8").pipe(response);
        // }
        
    }

    var server = http.createServer(onRequest);
    //最后让服务器监听一个端口
    server.listen(3000,"127.0.0.1");//还可以加第二个参数 127.0.0.1代表的是本地

    console.log("server started on localhost port 3000");//加一个服务器启动起来的提示
}

module.exports.startServer=startServer;

那么响应的app.js中startServer函数也要传进去对应的参数

var server = require("./server");
var router = require("./router");

server.startServer(router.route);

那么app.js中传给startServer函数的route,从哪来呢?

我们重新建立一个模块,叫router.js,它里面应该导出一个route函数

route需要有一个request.url参数

如下:

function route(pathname){
    console.log("Routing request for"+pathname);
}

module.exports.route=route;

上面route函数的pathname参数是在server.js里调用这个函数时传进去的,而api调用startServer时,传进去的是route函数本身,并不需要传参数。

做完上面的,服务器的请求,就到route.js中了,我们需要在route.js中对服务器请求做一些响应,当然如果直接在route.js中把一些if else写进去,还是比较乱,没多大意义,我们可以再重新建立一个模块:handler.js来写这些响应代码:

重构的目的肯定是想,让代码更整洁,更“智能化”,所谓的智能化,就是你只需要改变一小点地方,代码会把相应的改变,帮自己改变,不用自己去改变更多的代码。在代码中的体现,就是封装方法,传入不一样的参数,这个方法做出不一样的操作。那么,在现在的路由中,改变的是request.url,我们需要封装一个方法,根据request.url的不同,而做出对应的响应。下面的handler.js里面,盛放的是一些,对应的函数方法。

handler.js:

function home(){
    console.log("Executing 'home' handler");
}

function review(){
    console.log("Executing 'review' handler");
}

function api_records(){
    console.log("Executing 'api_records' handler");
}

module.exports={
    home,
    review,
    api_records
}

现在方法有了,需要与request.url发生对应关系,我们打算把这些对应关系放在api.js中:

api.js:

var server = require("./server");
var router = require("./router");
var handler = require("./handler");

var handle = {};

handle["/"]=handler.home;
handle["/home"]=handler.home;
handle["/review"]=handler.review;
handle["/api_records"]=handler.api_records;

server.startServer(router.route,handle);

我们把路径与方法的对应关系,写在了一个handle对象中,然后传给了startServer方法内

那么,stratServer方法需要作出响应更改:

server.js:

var http = require("http");
var fs = require("fs");

var startServer = function(route,handle){
    var onRequest = function(request,response){
        console.log("request received"+request.url);
        route(handle,request.url);
        // if(request.url==="/"||request.url==="/home"){
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
        // }else if(request.url==="/review"){
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
        // }else if(request.url==="/api"){
        //     response.writeHead(200,{"Content-Type":"application/json"});
        //     var jsonObj={name:"lili",job:"coder",age:18};
        //     response.end(JSON.stringify(jsonObj));
        // }else{
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/404.html","utf8").pipe(response);
        // }
        
    }

    var server = http.createServer(onRequest);
    //最后让服务器监听一个端口
    server.listen(3000,"127.0.0.1");//还可以加第二个参数 127.0.0.1代表的是本地

    console.log("server started on localhost port 3000");//加一个服务器启动起来的提示
}

module.exports.startServer=startServer;

我们把handle对象传给了stratServer方法,然后又传给了,route方法,那么route方法,需要更改:

route.js:

function route(handle,pathname){
    console.log("Routing request for"+pathname);
    if(typeof handle[pathname] === 'function'){
        handle[pathname]();
    }else{
        console.log("No handle for" + pathname);
    }
}

module.exports.route=route;

route方法内,判断当前路径对应的值是否是一个函数,是的话,执行这个函数,不是的话,后面处理,应该是跳转404页面,到后面处理

下一步,我们需要让handle方法做出相应,也就是响应给页面对应的内容,那么,我们就需要用到response对象,我们可以在stratServer中传给route方法:

var http = require("http");
var fs = require("fs");

var startServer = function(route,handle){
    var onRequest = function(request,response){
        console.log("request received"+request.url);
        route(handle,request.url,response);
        // if(request.url==="/"||request.url==="/home"){
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
        // }else if(request.url==="/review"){
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
        // }else if(request.url==="/api"){
        //     response.writeHead(200,{"Content-Type":"application/json"});
        //     var jsonObj={name:"lili",job:"coder",age:18};
        //     response.end(JSON.stringify(jsonObj));
        // }else{
        //     response.writeHead(200,{"Content-Type":"text/html"});
        //     fs.createReadStream(__dirname+"/404.html","utf8").pipe(response);
        // }
        
    }

    var server = http.createServer(onRequest);
    //最后让服务器监听一个端口
    server.listen(3000,"127.0.0.1");//还可以加第二个参数 127.0.0.1代表的是本地

    console.log("server started on localhost port 3000");//加一个服务器启动起来的提示
}

module.exports.startServer=startServer;

在router.js中也要穿进去:再传给handle方法:

function route(handle,pathname,response){
    console.log("Routing request for"+pathname);
    if(typeof handle[pathname] === 'function'){
        handle[pathname](response);
    }else{
        console.log("No handle for" + pathname);
    }
}

module.exports.route=route;

这样就可以在handle中,用response对象,响应给页面内容了

var fs = require("fs");

function home(response){
    response.writeHead(200,{"Content-Type":"text/html"});
    fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
}

function review(response){
    response.writeHead(200,{"Content-Type":"text/html"});
    fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
}

function api_records(response){
    response.writeHead(200,{"Content-Type":"application/json"});
    var jsonObj={name:"lili",job:"coder",age:18};
    response.end(JSON.stringify(jsonObj));
}

module.exports={
    home,
    review,
    api_records
}

此时,我们在localhost:3000 分别输入 / /home /review /api_records 都会响应出不同的内容!!

下面处理一下,当没有对应路径的方法时,跳转到404页面:

在router.js中变动:

var fs = require("fs");

function route(handle,pathname,response){
    console.log("Routing request for"+pathname);
    if(typeof handle[pathname] === 'function'){
        handle[pathname](response);
    }else{
        response.writeHead(200,{"Content-Type":"text/html"});
        fs.createReadStream(__dirname+"/404.html","utf8").pipe(response);
    }
}

module.exports.route=route;

以上就是 重构路由代码的整个过程

成型路由代码

上线的重构过程有些乱,下面把整个路由重构后的代码帖出来:

api.js:

var server = require("./server");
var router = require("./router");
var handler = require("./handler");

var handle = {};

handle["/"]=handler.home;
handle["/home"]=handler.home;
handle["/review"]=handler.review;
handle["/api_records"]=handler.api_records;

server.startServer(router.route,handle);

server.js:

var http = require("http");

var startServer = function(route,handle){
    var onRequest = function(request,response){
        console.log("request received"+request.url);
        route(handle,request.url,response);
        
    }

    var server = http.createServer(onRequest);
    //最后让服务器监听一个端口
    server.listen(3000,"127.0.0.1");//还可以加第二个参数 127.0.0.1代表的是本地

    console.log("server started on localhost port 3000");//加一个服务器启动起来的提示
}

module.exports.startServer=startServer;

router.js:

var fs = require("fs");

function route(handle,pathname,response){
    console.log("Routing request for"+pathname);
    if(typeof handle[pathname] === 'function'){
        handle[pathname](response);
    }else{
        response.writeHead(200,{"Content-Type":"text/html"});
        fs.createReadStream(__dirname+"/404.html","utf8").pipe(response);
    }
}

module.exports.route=route;

handler.js:

var fs = require("fs");

function home(response){
    response.writeHead(200,{"Content-Type":"text/html"});
    fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
}

function review(response){
    response.writeHead(200,{"Content-Type":"text/html"});
    fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
}

function api_records(response){
    response.writeHead(200,{"Content-Type":"application/json"});
    var jsonObj={name:"lili",job:"coder",age:18};
    response.end(JSON.stringify(jsonObj));
}

module.exports={
    home,
    review,
    api_records
}

上面就是成型的路由代码了,以后再添加新的路由,我们只需要该两处地方,1是,api中路径与handle方法的对应关系,2是,在handler.js中新增对应的方法!!!

比如说,我们加个text的路由,让它响应文本内容

api.js中:

var server = require("./server");
var router = require("./router");
var handler = require("./handler");

var handle = {};

handle["/"]=handler.home;
handle["/home"]=handler.home;
handle["/review"]=handler.review;
handle["/api_records"]=handler.api_records;
handle["/text"]=handler.text;

server.startServer(router.route,handle);

handler.js中:

var fs = require("fs");

function home(response){
    response.writeHead(200,{"Content-Type":"text/html"});
    fs.createReadStream(__dirname+"/index.html","utf8").pipe(response);
}

function review(response){
    response.writeHead(200,{"Content-Type":"text/html"});
    fs.createReadStream(__dirname+"/review.html","utf8").pipe(response);
}

function api_records(response){
    response.writeHead(200,{"Content-Type":"application/json"});
    var jsonObj={name:"lili",job:"coder",age:18};
    response.end(JSON.stringify(jsonObj));
}

function text(response){
    response.writeHead(200,{"Content-Type":"text/plain;charset=UTF-8"});
    response.end("文本内容");
}

module.exports={
    home,
    review,
    api_records,
    text
}

ok!!!