zoukankan      html  css  js  c++  java
  • express运行原理

    一、express底层:http模块

      Express框架建立在node.js内置的http模块上。http模块生成服务器的原始代码如下。

    var http = require("http");
    
    var app = http.createServer(function(request, response) {
      response.writeHead(200, {"Content-Type": "text/plain"});
      response.end("Hello world!");
    });
    
    app.listen(3000, "localhost");

      上面代码的关键是http模块的createServer方法,表示生成一个HTTP服务器实例。该方法接受一个回调函数,该回调函数的参数,分别为代表HTTP请求和HTTP回应的request对象和response对象。

      Express框架的核心是对http模块的再包装。上面的代码用Express改写如下。

    var express = require('express');
    var app = express();
    
    app.get('/', function (req, res) {
      res.send('Hello world!');
    });
    
    app.listen(3000);

      比较两段代码,可以看到它们非常接近。原来是用http.createServer方法新建一个app实例,现在则是用Express的构造方法,生成一个Epress实例。两者的回调函数都是相同的。Express框架等于在http模块之上,加了一个中间层。

    二、express中间件

      简单说,中间件(middleware)就是处理HTTP请求的函数。它最大的特点就是,一个中间件处理完,再传递给下一个中间件。App实例在运行过程中,会调用一系列的中间件。

      每个中间件可以从App实例,接收三个参数,依次为request对象(代表HTTP请求)、response对象(代表HTTP回应),next回调函数(代表下一个中间件)。每个中间件都可以对HTTP请求(request对象)进行加工,并且决定是否调用next方法,将request对象再传给下一个中间件。

      一个不进行任何操作、只传递request对象的中间件,就是下面这样。

    function uselessMiddleware(req, res, next) {
      next();
    }

      上面代码的next就是下一个中间件。如果它带有参数,则代表抛出一个错误,参数为错误文本。

    function uselessMiddleware(req, res, next) {
      next('出错了!');
    }

      抛出错误以后,后面的中间件将不再执行,直到发现一个错误处理函数为止。

      在 Node.js Web 开发中,各种模块基本采用这样的中间件格式:

    function (req, res, next) {
      // req 用于获取请求信息, ServerRequest 的实例
      // res 用于响应处理结果, ServerResponse 的实例
      // next() 函数用于将当前控制权转交给下一步处理,如果给 next() 传递一个参数时,表示出错信息
    }

      Express 是基于 Connect 的, Connect 中间件采用了以上的这种格式。 因此,当你要编写一个中间件时,编写一个以上格式的函数即可。

      其实跟编写 Express 的路由处理函数是没多大区别的,一些细微的差别是:

    • 中间件一般不直接对客户端进行响应,而是对请求进行一些预处理,再传递下去;
    • 中间件一般会在路由处理之前执行;

      比如:

    // 检查用户是否登录中间件,所有需要登录权限的页面都使用此中间件
    function checkLogin (req, res, next) {
      if (req.session.user) {
        next();
      } else {
        res.redirect('/');
      }
    } 

    三、USE方法

      use是express注册中间件的方法,它返回一个函数。下面是一个连续调用两个中间件的例子。

    var express = require("express");
    var http = require("http");
    
    var app = express();
    
    app.use(function(request, response, next) {
      console.log("In comes a " + request.method + " to " + request.url);
      next();
    });
    
    app.use(function(request, response) {
      response.writeHead(200, { "Content-Type": "text/plain" });
      response.end("Hello world!
    ");
    });
    
    http.createServer(app).listen(1337); 

      上面代码使用app.use方法,注册了两个中间件。收到HTTP请求后,先调用第一个中间件,在控制台输出一行信息,然后通过next方法,将执行权传给第二个中间件,输出HTTP回应。由于第二个中间件没有调用next方法,所以request对象就不再向后传递了。

    use方法内部可以对访问路径进行判断,据此就能实现简单的路由,根据不同的请求网址,返回不同的网页内容。

    var express = require("express");
    var http = require("http");
    
    var app = express();
    
    app.use(function(request, response, next) {
      if (request.url == "/") {
        response.writeHead(200, { "Content-Type": "text/plain" });
        response.end("Welcome to the homepage!
    ");
      } else {
        next();
      }
    });
    
    app.use(function(request, response, next) {
      if (request.url == "/about") {
        response.writeHead(200, { "Content-Type": "text/plain" });
      } else {
        next();
      }
    });
    
    app.use(function(request, response) {
      response.writeHead(404, { "Content-Type": "text/plain" });
      response.end("404 error!
    ");
    });
    
    http.createServer(app).listen(1337); 

      上面代码通过request.url属性,判断请求的网址,从而返回不同的内容。注意,app.use方法一共登记了三个中间件,只要请求路径匹配,就不会将执行权交给下一个中间件。因此,最后一个中间件会返回404错误,即前面的中间件都没匹配请求路径,找不到所要请求的资源。

      除了在回调函数内部,判断请求的网址,use方法也允许将请求网址写在第一个参数。这代表,只有请求路径匹配这个参数,后面的中间件才会生效。无疑,这样写更加清晰和方便。

    app.use('/', someMiddleware); 

      上面代码表示,只对根目录的请求,调用某个中间件。

      因此,上面的代码可以写成下面的样子。

      

    var express = require("express");
    var http = require("http");
    
    var app = express();
    
    app.use("/", function(request, response, next) {
      response.writeHead(200, { "Content-Type": "text/plain" });
      response.end("Welcome to the homepage!
    ");
    });
    
    app.use("/about", function(request, response, next) {
      response.writeHead(200, { "Content-Type": "text/plain" });
      response.end("Welcome to the about page!
    ");
    });
    
    app.use(function(request, response) {
      response.writeHead(404, { "Content-Type": "text/plain" });
      response.end("404 error!
    ");
    });
    
    http.createServer(app).listen(1337);

      参考资料:

      http://javascript.ruanyifeng.com/nodejs/express.html

      

  • 相关阅读:
    Building Java Projects with Gradle
    Vert.x简介
    Spring及Spring Boot 国内快速开发框架
    dip vs di vs ioc
    Tools (StExBar vs Cmder)which can switch to command line window on context menu in windows OS
    SSO的定义、原理、组件及应用
    ModSecurity is an open source, cross-platform web application firewall (WAF) module.
    TDD中测试替身学习总结
    Spring事务银行转账示例
    台式机(华硕主板)前面板音频接口(耳机和麦克风)均无声的解决办法
  • 原文地址:https://www.cnblogs.com/pingfan1990/p/4860389.html
Copyright © 2011-2022 走看看