zoukankan      html  css  js  c++  java
  • Node_进阶_3

    Express框架:

    一、   Express框架

    Express框架是后台的Node框架,类似于JS中的jquery。

    #原生Node开发会有很多问题:

     1呈递静态页面很不方便,需要处理每个HTTP请求,还要考虑304问题

     2路由处理代码不直观清晰,需要写很多正则表达式和字符串函数

     3不能集中精力写业务,要考虑很多其他的东西

    我们自己可以把第一天的作业,就是那个静态文件服务封装成为模块。封装的越多,就自己做出了类似Express的东西。

    Express的哲学就是在你的想法和服务器之间充当薄薄的一层。这并不意味着它不够健壮,或者没有足够的有用特性,而是尽量少干预你,让你充分表达自己的思想,同时提供一些有用的东西。

    http://www.expressjs.com.cn/

    整体感知,Express框架:

    1.expres惊艳的路由能力

    var express = require('express');

     

    var app = express();

     

    app.get('/', (req, res) => {

        res.send('你好');

    });

     

    app.get('/haha', (req, res) => {

        res.send('这是haha页面,哈哈哈');

    });

     

    app.get(/^/student/([d]{6})$/, (req, res) => {

     

        //正则中的()表示分组提取 第[0]个

        res.send('学生信息,学号' + req.params[0]);

     

    });

     

    //冒号可以被req得到

    app.get('/teacher/:gonghao', (req, res) => {

        //

        res.send('老师信息,工号' + req.params.gonghao);

     

    });

     

    app.listen(2888);

     2.Express静态文件的伺服能力。

    const express = require('express');

     

    var app = express();

     

    //使用中间件:(在当前目录的public文件夹下有index.html 这时GET / 的时候会自动读出index.html)

    app.use(express.static('./public'));

     

    app.get('/haha', (req, res) => {

     

        res.send('haha');

     

    });

     

    app.listen(2888);

    3.Express与模板引擎的配合,直观清晰,天呐撸

    haha.ejs:

    <!DOCTYPE html>

    <html lang="en">

     

    <head>

        <meta charset="UTF-8">

        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <meta http-equiv="X-UA-Compatible" content="ie=edge">

        <title>Document</title>

    </head>

     

    <body>

        <h1>哈哈哈哈</h1>

        <ul>

            <% for(var i = 0;i<news.length;i++){%>

                <li>

                    <%= news[i] %>

                </li>

                <% } %>

        </ul>

    </body>

     

    </html>

    3.js:

    const express = require('express');

     

    var app = express();

     

    app.set('view engine','ejs');

     

    app.get('/',(req,res)=>{

     

        //默认就是views/文件夹下

        res.render('haha.ejs',{

            news:['我是小新闻啊','我也是啊','天啦噜']

        })

     

    });

     

    app.listen(2888);

    二、路由

    我们学习的是Express4.x和Express3.x差别非常大。

    用get请求访问一个网址

    app.get(‘网址’,(req,res)=>{

    });

    app.post(‘网址’,(req,res)=>{

    });

    restful

    如果想除了这个网址的任何methods的请求

    app.all(‘/’,(req,res)=>{

    })

    app.get(‘/AAb’,(req,res)=>{

    res.send(‘你好’);

    })

    实际上小写的访问也行。

    所有的GET参数,?都已经被忽略。 锚点#也被忽略

    你路由到/a,实际/a?id=2&sex=nan 也能被处理

    正则表达式可以被使用。正则表达式中,未知部分用圆括号分组,然后可以用req.params[0]、req.params[1]来获取。

    app.get(/^/student/([d]{10})$/,(req,res)=>{

    res.send(‘学生信息,学号’ + req.params[0]);

    });

    冒号是更推荐的写法。

    const express = require('express');

     

    var app = express();

     

    app.get('/:username/:oid',(req,res)=>{

     

        var username = req.params.username;

        var oid = req.params.oid;

     

        res.write(username);

        res.end(oid);

     

    });

     

    app.listen(2888);

    表单可以自己提交到自己:

    05.js:

     

    const express = require('express');

    const app = express();

     

    //设置模板引擎

    app.set('view engine', 'ejs');

     

    app.get('/', (req, res) => {

     

        res.render('form');

     

    });

     

    app.post('/', (req, res) => {

        //将数据添加进入数据库

        res.send('成功');

     

    });

     

    app.listen(2888);

    适合进行RESTful路由设计。

    RESTful路由设计

    /students

    get 读取学生信息

    post 修改学生信息

    delete 删除学生信息

    【用express来实现非常简单】

    app.get、app,post、app,delete...

    总结:这节课比较重点的地方是 路由,路由的话,app.get(‘’)这里面可以写正则表达式,用()来捕获,也可以写:,最后用req.params[0] 或者req.params.xxx来获取,推荐的是使用:冒号的方式。

    一、          中间件

    //这个就叫做中间件

    app.get('/',(req,res)=>{

        console.log('2');

    });

    顾名思义,中间件(middleware)作为请求和响应之间的中间人,用于处理HTTP请求,返回特定结果。

    如果我的get、post回调函数中,没有next参数,那么匹配上第一个中间件后就不会往下继续匹配了,如果向往下匹配的话,那么需要写next();

    app.get('/',(req,res,next)=>{

     

        console.log('1');

        next();

    });

     

    //这个就叫做中间件

    app.get('/',(req,res)=>{

        console.log('2');

    });

    下面两个路由,感觉没有关系:

    app.get('/:username/:id', (req, res) => {

        console.log('1');

        res.send('用户信息'+req.params.username);

    });

     

    //这个就叫做中间件

    app.get('/admin/login', (req, res) => {

        console.log('2');

        res.send('管理员登陆');

    });

    但是实际上冲突了,因为admin可以当作用户名 login可以当作id。

    解决方法1:交换位置,也就是说,express中所有的路由(中间件)的顺序至关重要。

    匹配上第一个,就不会往下匹配了。具体的网上写,抽象的往下写。

    主要规则:(写路由表的时候,越具体的越要往上写,越抽象的越要往下写)

    解决方法2:使用next()

    const express = require('express');

     

    var app = express();

     

    var a = 100;

     

    //这个就叫做中间件

    app.get('/admin/login', (req, res) => {

      

        var username = req.params.username;

     

        //检索数据库,如果username不存在,那么next

        if(检索数据库){

            console.log('2');

            res.send('管理员登陆');

        }

        else{

            next();

        }  

     

    });

     

    app.get('/:username/:id', (req, res) => {

        console.log('1');

        res.send('用户信息'+req.params.username);

    });



    app.listen(2888);

    路由get、post这些东西,就是中间件,中间件讲究顺序,匹配上第一个之后就不会往后匹配了。除非写了next()之后才能够继续往后匹配。

    app.use:

    举例,如果我GET /admin 返回’hello world’ 那么我GET /admin/asd 也会返回’hello world’.

    app.use('/admin', function(req, res, next) {

      // GET 'http://www.example.com/admin/new/asd/asd'

      console.log(req.originalUrl); // '/admin/new'

      console.log(req.baseUrl); // '/admin'

      console.log(req.path); // '/new/asd/asd'

      next();

    });

    app.use也是一个中间件,它与get和post的不同是,它的网址不是精确匹配的,而是有拓展的。

    所以:

    app.use(‘/’,(req,res)=>{

    })

    //这样就会出现骚操作。所有的请求是/的扩展,所以…

    但是要写next();否则会卡在这个中间件。

    app.use(‘/’,(req,res)=>{

    console.log(‘haha’);

    next();

    })

    还可以这样简写:

    //不写就相当于‘/’

    app.use((req,res)=>{

    console.log(‘haha’);

    next();

    })

    app.use()就给我们增加一些特定功能的便利场所。

    自带的静态服务:

    app.use(express.static(‘./public’));

    //使用了app.use这个方法,使用了封装好的express.static这个中间件,这个静态服没有next方法(),一般把它放在代码的上边部分,防止做路由的时候和现有文件冲突,

      比如你有一个image文件夹就没必要再做/image路由转到别的地方。直接读这个文件夹就好了。

    //其实似乎这两个广义地讲都叫中间件..

    (但是我们其实编程时候不怎么使用app.use方法,因为这很不MVC)

    app.use(‘/jingtai’,express.static(‘./public’));

    ·大多数情况下,渲染内容用res.render(),将会根据views中的模板文件进行渲染。如果不想使用view文件夹,想自己设置文件夹名字,那么app.set(‘views’,’…’)

    ·如果想写一个快速测试页,当然可以使用res.send()。这个函数 将根据内容,自动帮我们设置了Content-Type头部和200状态吗。send()只能用一次,和end一样。和end不一样在哪里?能够自动设置MIME

    ·如果想使用不同的状态吗,可以:

      res.status(404).send(‘Sorry,we cannot find that’)

    ·如果想使用不同的Content-Type,可以:

    res.set(‘Content-Type’,’text,html’);

    app.set…

    (…这些都可以被set,如果需要使用请详细查看官网文档)

    四、GET请求和POST请求

    ·GET请求的参数在URL中,在原生Node中,需要使用url模块来识别参数字符串。在Express中,不需要使用url模块来parse了,可以直接使用req.query对象。

    ·POST请求在express中不能直接获得,必须使用body-parser模块,使用后,将可以用req.body得到参数。但是如果表单中含有文件上传,那么还是需要使用formidable模块。

    req.query打印出的是一个对象,比如GET ?a=1&b=2 返回的就是:{a:1,b:2}

    POST引擎需要引用body-parser中间件

      req.body打印出一个对象

    12.js:

    const express = require('express');

     

    var app = express();

    var bodyParser = require('body-parser');

     

    app.set('view engine', 'ejs');

     

    app.get('/', (req, res) => {

     

        res.render('form');

     

    });

     

    app.use(bodyParser.urlencoded({ extended: false }));

     

    app.post('/', (req, res) => {

        res.send(req.body);

    });

     

    app.listen(3333);

    捋捋api:

     

    主要来看一下最后一个Route,Route是个啥.

    以下内容摘抄自网络:

    ———————————————————————————————————————

    当你调用 express() 方法时,就创建了一个 Application。事实上这个 Application 也只不过是对 Router 的一个轻量级封装而已。

    每个 Application 内部都创建了一个 Router,大部分对 Application 的操作实际上都被重定向到了这个内部的 Router 上而已。而 Application 所做的,只不过是在这个 Router 的基础上添加了一些额外的便捷 API 而已。

    举个例子,当你调用 app.get(...) 或者 app.use(...) 的时候,实际上真正调用的是 app._router.get(...) 或者 app_router.use(...)。

    所以,Application 和 Router 的区别便很清楚了,Application 是 Router 的一个“包装”,而 Router 才是“核心”。

    router.get is only for defining subpaths. Consider this example:

    var router = express.Router();
     
    app.use('/first', router); // Mount the router as middleware at path /first
     
    router.get('/sud', smaller);
     
    router.get('/user', bigger);

    Now if you will open /first/sud in your browser, then smaller function will get called. If you will open first/user, then bigger will gets called. In short, app.use('/first', router) mounts the middleware at path /first, then router.get sets the subpath accordingly.

    But if we instead use:

    app.use('/first', fun);
     
    app.get('/sud', bigger);
     
    app.get('/user', smaller);

    Now if you will open /first in your browser then fun will get called and for /sud, bigger will get called and for /user, the function smaller will get called. ...but remember here for /first/sud, no function will get called.

    回答者要传达的意思是:“路由级别的中间件,可以作为app级别的中间件的扩展,从而减小app级别路径处理的臃肿,提高可维护性和扩展性”。

    强行比喻一下:

    产品经理通过应用级别的中间件,控制一级路径;然后各个项目经理,在此基础上,自己通过路由级别的中间件,控制二级路径(项目经理不用考虑产品经理是怎么处理一级路径的)。

    ——————————————————————————————————

    小小相册项目:

    //前端语言与后端语言

    本质区别:前端是在用户电脑运行,后端是在服务器运行

    Node中全是回调函数,所以我们自己封装的函数,里面如果有异步方法,比如I/O,那么就要用回调函数的方法封装。

    错误

    res.render(“index”,

    {“name”:student.getDetailById(234234).name});

    正确

    student.getDetailByXuHao(234234,function(detail){

    res.render(“index”,{

        “name”:detail.name

    })

    })

  • 相关阅读:
    POJ 3041 Asteroids 二分图匹配
    ZOJ 3705 Applications 模拟
    UNIX环境高级编程(第3版)
    明清美文四卷本(共四册)
    卑鄙的圣人:曹操(全10册)
    爱丽丝梦游仙境
    我在大清官场30年
    乌合之众:大众心理研究
    Java多线程编程实战指南
    Linux就该这么学
  • 原文地址:https://www.cnblogs.com/eret9616/p/9111300.html
Copyright © 2011-2022 走看看