美文网首页
Express框架

Express框架

作者: 殘缺的回忆 | 来源:发表于2019-06-09 22:12 被阅读0次

    1. 课程介绍

    ◆ Express介绍(了解)

    ◆ Express安装及使用(掌握)

    ◆ Express路由(掌握)

    ◆ response响应对象(掌握)

    ◆ request请求对象(掌握)

    ◆ 中间件(了解)

    2. Express介绍

    Express 是一个基于 Node.js 平台的极简、灵活的 web 应用开发框架,它提供一系列强大的特性,帮助你创建各种 Web 和移动设备应用。

    Express 框架核心特性:

    n 可以设置中间件来响应 HTTP 请求。
    n 定义了路由表用于执行不同的 HTTP 请求动作。
    (url = 资源) 映射
    n 可以通过向模板传递参数来动态渲染 HTML 页面。 模板引擎

    3. Express使用

    3.1. 简单使用(了解)

    1、新建一个NodeJs项目文件夹

    2、npm init 初始化项目配置文件(package.json 包描述文件)

    package.json中

     **"scripts"**: {
    
     //命令 **"start"**:**"node ./index"
      **}
    
     npm start 执行”start”后面的代码。
    

    3、安装express

    npm install express --save
    

    4、编写一个app.js使用express

     *//**导入**express**模块***var** **express** = *require*(**"express"**); *//**创建一个**express**应用***var** ***app*** = **express**(); *//**处理**"/"**请求****app***.get(**"/"**,**function**(req,res){
           *//**响应输出**“hello world”
           *res.send(**"Hello world"**);
     }); *//**启动服务器监听**3000**端口****app***.listen(3000,**function**(){
            ***console***.log(**"express app** **启动成功。。。****"**);
     });
    

    5、启动服务器

    node app.js
    

    6、浏览器访问

    3.2. Express-generator(重点)

    为了快速的创建express项目,express团队为使用者提供了项目快速生成工具,express-generator

    1、安装express-generator

    npm i express-generator -g //全局安装

    2、新建一个目录(或者找一个空目录)

    F:\webproject (目录可以新建在任何位置,但最好不要中文路径)

    3、通过命令创建express项目

    express -e projecname(express代表在当前目录下面建立express项目 -e代表使用ejs模版引擎)

    **express webapp **(代表在当前目录下面,新建一个webapp文件夹,然后在建立express项目)

    项目结构:

    bin : 执行文件,也是express项目启动文件。
    
    public:公共的资源,浏览器可以直接访问的资源。(图片,js,css)
    
    views:服务器端模块文件。
    
    routes:路由处理器,处理浏览器发出不同url的处理程序。
    
    /login function(){
    
    //登录处理程序
    
    }
    

    app.js express应用的主文件,该文件主要用于整合其他第三方模块和配置express的系统参数。

    4、安装依赖包

    通过package.json

    **"dependencies"**: { **"body-parser"**: **"~1.15.1"**, **"cookie-parser"**: **"~1.4.3"**, **"debug"**: **"~2.2.0"**, **"ejs"**: **"~2.4.1"**, **"express"**: **"~4.13.4"**, **"morgan"**: **"~1.7.0"**, **"serve-favicon"**: **"~2.3.0"** }
    
      **npm i**
    

    5、启动express

    node app需要设置监听端口
    npm start
    node ./bin/www

    6、浏览器访问

    3.3. Express服务器项目结构说明

     bin: 执行文件,也是express项目启动文件。
    
     public: 公共的资源(nodejs不做处理),浏览器可以直接访问的资源,相当于静态网页的根目录,访问时不需加路径。(图片,js,css)
    
     http://localhost:3000/test.html
    
     http://localhost:3000/images/img.jpg
    
     views: 服务器端模块或模板文件。
    
     routes: 路由处理器,处理浏览器发出不同url的处理程序。动态网页的目录
    
     ----------------------------------------------------------------------------------
    
     app.js 主模块文件,是总路由,分支路由写在routes目录下
    
     package.json 包管理,依赖包
    
     //引入系统和第三方模块
    
     var express = require('express');
    
     var path = require('path');
    
     var favicon = require('serve-favicon');
    
     var logger = require('morgan');
    
     var cookieParser = require('cookie-parser');
    
     var bodyParser = require('body-parser');
    
     //引入路由
    
     var index = require('./routes/index');
    
     var users = require('./routes/users');
    
     var vipCenter=require("./routes/vip");
    
     //实例化express框架
    
     var app = express();
    
     // view engine setup
    
     //设置模板的默认目录
    
     app.set('views', path.join(__dirname, 'views'));
    
     //设置ejs为模板引擎
    
     app.set('view engine', 'ejs');
    
     // uncomment after placing your favicon in /public
    
     //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
    
     //中间件
    
     app.use(logger('dev'));
    
     app.use(bodyParser.json());
    
     app.use(bodyParser.urlencoded({ extended: false }));
    
     app.use(cookieParser());
    
     //设置静态目录为public
    
     app.use(express.static(path.join(__dirname, 'public')));
    
     //使用分路由
    
     app.use('/', index);
    
     app.use('/users', users);
    
     app.use("/vip",vipCenter);
    
     // catch 404 and forward to error handler
    
     //404找不到
    
     app.use(function(req, res, next) {
    
     var err = new Error('Not Found');
    
     err.status = 404;
    
     next(err);
    
     });
    
     // error handler
    
     //错误
    
     app.use(function(err, req, res, next) {
    
     // set locals, only providing error in development
    
     res.locals.message = err.message;
    
     res.locals.error = req.app.get('env') === 'development' ? err : {};
    
     // render the error page
    
     res.status(err.status || 500);
    
     res.render('error');
    
     });
    
     //导出模块
    
    module.exports = app;
    

    4. Express路由(重点)

    路由是指如何定义应用的端点(URIs)以及如何响应客户端的请求。
    路由是由一个 URI、HTTP 请求(GET、POST等)和若干个句柄(函数)组成,它的结构如下: app.METHOD(path, [callback...], callback), app 是 express 对象的一个实例, METHOD 是一个 HTTP 请求方法, path 是服务器上的路径, callback 是当路由匹配时要执行的函数。

    4.1. 基础用法

    var express = require('express');
    
    var app = express();
    
    //设置请求路径“/”对应的处理器
    
    app.get('/', function(req, res) {
    
     res.send('hello world');
    
    });
    

    4.2. 路由方法

    路由与HTTP 请求方法(GET、POST)相关联。
    为应用“/”路径定义的 GET 和 POST 请求:

    // 处理get请求方式,超链接、浏览器地址栏直接访问
    
    app.get('/', function (req, res) {
    
     res.send('处理get请求');
    
    });
    
    // 处理post请求方式,表单提交
    
    app.post('/', function (req, res) {
    
     res.send('处理post请求');
    
    });
    
    app.all() 是一个特殊的路由方法,没有任何 HTTP 方法与其对应,它的作用是对于一个路径上的所有请求加载中间件。 all相当于既可以处理GET,也可以处理POST。
    
    app.all('/, function (req, res, next) {
    
     res.send('任意方式的请求');
    
    });
    

    4.3. Router(重点中的重点)

    express.Router类可以创建模块化(独立的)、可挂载的路由对象。Router对象是一个完整的中间件和路由系统,因此常称其为一个 “mini-app”。

    1、新建一个模块vip.js(express项目要求我们放到routes

    var express = require('express');
    
    var router = express.Router();
    
    // 定义模块的主页的路由
    
    router.get('/', function(req, res) {
    
     res.send('vip首页');
    
    });
    
    // 定义模块“/getScore”路径的路由
    
    router.get('/getScore', function(req, res) {
    
     res.send('vip积分');
    
    });
    
    module.exports = router;
    
    **2****、app.js** **使用**
    
    var vip = require('./vip);
    
    ...
    
    app.use('/vip', vip); // 路径“/vip”使用vip路由模块,这个行为就是把“vip”模块挂载到“/vip”路径下面。
    

    访问

    http://localhost:3000/vip/ //vip首页
    http://localhost:3000/vip/getScore //vip积分

    5. 响应对象(重点)

    响应对象(res)的方法向客户端返回响应,终结请求响应的循环。如果在路由函数中一个方法也不调用,来自客户端的请求会一直挂起。

    5.1. send方法(重点中的重点)

    send(data) 可以返回任意类型数据。
    
    res.send(new Buffer('whoop'));//流
    
    res.send({ some: 'json' });// json数据
    
    res.send('<p>some html</p>');//普通文本
    
    //设置状态码,并且返回内容
    
    res.status(404).send('Sorry, we cannot find that!');
    
    res.status(500).send({ error: 'something blew up' });
    

    5.2. json方法

    json(data) 返回json对象,一般针对ajax应用。
    
    res.json(null);
    
    res.json({ user: 'tobi' });
    
    //设置状态码,并返回json数据
    
    res.status(500).json({ error: 'message' });
    

    5.3. jsonp方法

    jsonp(data) 返回json对象,一般针对ajax的跨域访问。
    
    res.jsonp(null);
    
    res.jsonp({ user: 'tobi' });
    
    //设置状态码,并返回json数据
    
    res.status(500).jsonp({ error: 'message' });
    

    5.4. render视图模板

    ejs模板的使用
    index.ejs模板
    
    <!DOCTYPE html>
    
    <html>
    
     <head>
    
     <title><%= title %></title>
    
     <link rel='stylesheet' href='/stylesheets/style.css' />
    
     </head>
    
     <body>
    
     <ul id="mainNav">
    
     <li><a href="/">首页</a></li>
    
     <li><a href="/news">新闻中心</a></li>
    
     <li><a href="/vip">vip会员中心</a></li>
    
     <li><a href="/users">用户注册</a></li>
    
     </ul>
    
     <h1><%= title %></h1>
    
     <p>Welcome to <%= title %></p>
    
     </body>
    
    </html>
    
    **index.js** **路由**
    
    var express = require('express');
    
    var router = express.Router();
    
    /* GET home page. */
    
    router.get('/', function(req, res, next) {
    
     res.render('index', { title: 'Express' }); //将视图和数据合并后发送给客户端
    
    });
    
    module.exports = router;
    

    5.5. download下载

    //下载当前目录下面的xxx.doc文件,并且重命名为yyy.doc。
    
    router.get('/down', function(req, res, next) {
    
     res.download("./downTest.doc","express使用说明.doc")
    
    });
    
    5.6. redirect重定向
    
     重定向到从指定的URL路径(浏览器地址变为设置的地址)
    
     router.get('/it', function(req, res, next) {
    
     res.redirect("http://www.baidu.cn");
    
    });
    

    5.7. 404报错页面制作

    router.get('/err', function(req, res, next) {
    
     //res.status(404).send("出错了:文件没有找到!");
    
     res.status(404).render("error",{message:"很抱歉,您查看的宝贝不存在,可能已下架或者被转移。"});
    
    });
    
    error.ejs
    
    <h1><%= message %></h1>
    
    <p><img src="./images/err.png" /></p>
    

    5.8. 完整api

    1. res.app:同req.app一样
    
    2. res.append():追加指定HTTP头
    
    3. res.set()在res.append()后将重置之前设置的头
    
    4. res.cookie(name,value [,option]):设置Cookie
    
    opition: domain / expires / httpOnly / maxAge / path / secure / signed
    
    5. res.clearCookie():清除Cookie
    
    npm install cookie
    
    var cookie=require("cookie");
    
    res.cookie("username",username); // 设置cookie
    
    req.cookies.名称 // 取值
    
    res.clearCookie(‘名称’); // 清除指定名称的Cookie
    
    手动清除cookie,设置》高级》清除浏览数据
    
    router.get("/checkLogin",function(req,res,next){
    
     var username=req.cookies.username;
    
     if(username) {
    
     res.send(true);
    
     }
    
     else{
    
     res.send(false);
    
     }
    
    });
    
    6. res.download():传送指定路径的文件
    
    7. res.get():返回指定的HTTP头
    
    8. res.json():传送JSON响应
    
    9. res.jsonp():传送JSONP响应
    
    10. res.location():只设置响应的Location HTTP头,不设置状态码或者close response
    
    11. res.redirect():设置响应的Location HTTP头,并且设置状态码302
    
    12. res.send():传送HTTP响应
    
    13. res.sendFile(path [,options] [,fn]):传送指定路径的文件 -会自动根据文件extension设定Content-Type
    
    14. res.set():设置HTTP头,传入object可以一次设置多个头
    
    15. res.status():设置HTTP状态码
    
    16. res.type():设置Content-Type的MIME类型
    

    6. 请求对象(重点)

    req(request)对象包含了数一次请求中的所有据(http头信息、请求参数...)

    6.1. 获取浏览器地址栏中的参数(重点中的重点)

    语法: req.query.参数名;
    
    比如:http://localhost:3000/user?name=007
    
     req.query.name;
    
      **搜索功能**
    
    search.html?keywords=笔记本电脑&catetype=it数码
    
    router.get('/search.html', function(req, res, next) {
    
     var keywords=req.query.keywords;
    
     var catetype=req.query.catetype;
    
     res.json({"关键词":keywords,"类别":catetype});
    
    });
    

    6.2. 获取表单提交的值(重点中的重点)

    Post提交 req.body.参数名
    
    Get提交 req.query.参数名;
    
    **login.html** public静态文件
    
     <form action="/loginPost" method="post">
    
     <p>用户账号 <input type="text" name="username" /></p>
    
     <p>登录密码 <input type="password" name="pwd" /></p>
    
     <p><input type="submit" value="Post登录" /> </p>
    
     </form>
    
     <hr/>
    
     <form action="/loginGet" method="get">
    
     <p>用户账号 <input type="text" name="username" /></p>
    
     <p>登录密码 <input type="password" name="pwd" /></p>
    
      <p><input type="submit" value="Get登录" /> </p>
    
     </form>
    
      路由文件
    
    router.get('/loginGet', function(req, res, next) {
    
     var username=req.query.username;
    
     var pwd=req.query.pwd;
    
     res.json({"账号":username,"密码":pwd});
    
    });
    
    router.post('/loginPost', function(req, res, next) {
    
     var username=req.body.username;
    
     var pwd=req.body.pwd;
    
     res.json({"账号":username,"密码":pwd});
    
    });
    

    6.3. 获取路由中的参数parameters

      京东的产品地址:[https://item.jd.com/5268701.html](https://item.jd.com/5268701.html)
    
     /product/9999
    
     router.get("/product/:id",function(req,res){
    
     var productID=req.params.id;
    
     res.send("产品的编号是:"+productID);
    
    });
    
     parameter [pəˈræmɪtɚ] params [pəˈræms]
    
    伪静态: 看起来是一个静态文件,但其实是动态的。好处可以方便搜索引擎收录
    

    6.4. 获取ip地址

    router.get('/home', function(req, res, next) {
    
     res.send("<h1>我是首页homepage!!!</h1><p>你的ip地址是:"+req.hostname+"_"+req.ip+"</p>");
    
    });
    

    6.5. 完整api

    1. req.app:当callback为外部文件时,用req.app访问express的实例
    
    2. req.baseUrl:获取路由当前安装的URL路径
    
    3. req.body / req.cookies:获得「请求主体」/ Cookies
    
    4. req.fresh / req.stale:判断请求是否还「新鲜」
    
    5. req.hostname / req.ip:获取主机名和IP地址
    
    6. req.originalUrl:获取原始请求URL
    
    7. req.params:获取路由的parameters
    
    8. req.path:获取请求路径
    
    9. req.protocol:获取协议类型
    
    10. req.query:获取URL的查询参数串
    
    11. req.route:获取当前匹配的路由
    
    12. req.subdomains:获取子域名
    
    13. req.accpets():检查请求的Accept头的请求类型
    
    14. req.acceptsCharsets / req.acceptsEncodings / req.acceptsLanguages
    
    15. req.get():获取指定的HTTP请求头
    
    16. req.is():判断请求头Content-Type的MIME类型
    

    7. 中间件(了解)

    Express 是一个自身功能极简,完全是由路由中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。

    7.1. 中间件到底是什么

    中间件(Middleware)本质就是一个函数,它可以访问请求对象(request object),响应对象(response object),和 web应用中处于请求-响应循环流程中的中间件,一般被命名为 next的变量。(next尾函数,执行下一个任务)

    中间件的功能包括:
    1.执行任何代码。
    2.修改请求和响应对象。
    3.终结请求-响应循环。
    4.调用堆栈中的下一个中间件。
    如果当前中间件没有终结请求-响应循环,则必须调用 next() 方法将控制权交给下一个中间件,否则请求就会挂起。

    7.2. 应用级中间件

    应用级中间件绑定到 app对象使用 app.use()和 app.METHOD(),其中, METHOD是需要处理的 HTTP请求的方法,例如 GET, PUT, POST等等,全部小写。

    //最简单的中间件
    
    app.js
    
    var express = require('express');
    
    var app = express();
    
    …………………………. ………………………….
    
    /*
    
    * 中间件:
    
    *  1\. 中间件是一个函数
    
    *  2\. 中间件可以访问请求对象和响应对象
    
    *  3\. 可以阻止请求继续执行,如果不阻止,可以调用尾函数 next()
    
     *
    
    * 尾函数next:
    
    *  1\. 在一个中间件中执行尾函数,就可以调用下一个中间件
    
    *  2\. 如果不用调用尾函数,就阻止执行
    
    *  3\. 在尾函数后面的代码会执行,并且是在尾函数调起的下一个中间件结束后才执行
    
     */
    
     app.use(function(req,res,next){
    
     console.log('111');
    
     next();
    
     console.log('222');
    
     });
    
     app.use(function(req,res,next){
    
     console.log('333');
    
     next();
    
     console.log('444');
    
     });
    
    …………………………. ………………………….
    
    module.exports = app;
    

    7.3. 内置中间件

    Express中只为我们提供了唯一一个中间件,其他的中间件需要安装。

    下面的例子使用了 express.static中间件,其中的 options 对象经过了精心的设计。

    var options =  {
    
     dotfiles:  'ignore',
    
     etag:  false,
    
     extensions:  ['htm',  'html'],
    
     index:  false,
    
     maxAge:  '1d',
    
     redirect:  false,
    
     setHeaders:  function  (res, path, stat)  {
    
     res.set('x-timestamp', Date.now());
    
      }}
    
    app.use(express.static('public', options));
    
    每个应用可有多个静态目录。
    
    app.use(express.static('public'));
    
    app.use(express.static('uploads'));
    
    app.use(express.static('files'));
    
    app.use(logger('dev')); //控制台日志显示的中间件
    
    app.use(express.static(path.join(__dirname, 'public'))); //静态资源目录的中间件
    

    7.4. 第三方中间件

    通过使用第三方中间件从而为 Express 应用增加更多功能。
    安装所需功能的 node 模块,并在应用中加载,可以在应用级加载,也可以在路由级加载。
    Multer 翻译文档https://github.com/expressjs/multer/blob/master/doc/README-zh-cn.md

    文件上传中间件的使用

    fileUpload.html 静态页面
    
     <form action="/upload" method="post" **enctype**="multipart/form-data">
    
     <h2>图片上传</h2>
    
     <input type="file" name="imgUpload">
    
     <input type="submit" value="上传">
    
     </form>
    
    index.js 路由
    
    
     * npm i multer --save
    
     *
    

    前端准备工作:

    1、需要一个表单,表单里面必须有一个文件域
    2、必须给form表单指定enctype="multipart/form-data" 属性。
    3、提交按钮类型为submit。

    ** 后端:接收请求**

    1:前端请求表单页面http://127.0.0.1/upload/
    2:渲染模板,不需加载额外的数据。

    ** 教程:**

    http://blog.csdn.net/CatieCarter/article/details/77841208

    https://github.com/expressjs/multer

    //引入文件模块
    
    var fs = require("fs");
    
    //引入上传中间件模块
    
    var multer = require('multer');
    
    //初始化上传目录,自定义本地保存的路径
    
    //var upload = multer({ dest: './files/' }); //使用storage时不需要单独制定目录,storage中有目录设置
    
    var uploadFolder='./public/files/'; //放入静态资源目录才能正常显示
    
    // 通过storage的 filename 属性定制上传文件名称
    
    var storage = multer.diskStorage({
    
     destination: function (req, file, cb) {
    
     cb(null, uploadFolder); // 保存的路径,备注:需要自己创建如果不存在会报错
    
     },
    
     filename: function (req, file, cb) {
    
     //将保存文件名设置为 前缀+时间戳+文件扩展名
    
     var extName=file.originalname.substring(file.originalname.lastIndexOf(".")); //.jpg
    
     cb(null, file.fieldname + '_' + new Date().getTime() + extName);
    
     }
    
    });
    
    // 通过 storage 选项来对 上传行为 进行定制化
    
    var upload = multer({ storage: storage });
    
    //文件上传的路由,upload.single("imgUpload")指定单个文件上传,上传框的名称为imgUpload
    
    router.post('/upload',upload.single("imgUpload"), function(req, res, next) {
    
     var fileInfo = req.file; //multer会将文件的信息写到 req.file上
    
     console.log('文件类型:', fileInfo.mimetype);
    
     console.log('原始文件名:', fileInfo.originalname);
    
     console.log('文件大小:', fileInfo.size);
    
     console.log('文件保存路径:', fileInfo.path);
    
     //渲染图片显示的模板,直接获取文件存放的地址,显示时不需要public目录
    
     var filepath=fileInfo.path.toString().replace("public","");
    
     res.render("imgFileList.ejs",{imgShow: filepath});
    
     //直接显示出来
    
     res.set({"Content-Type":"text/html"});
    
     res.send("<img src='"+fileInfo.path.toString().replace("public","")+"' />");
    
    });
    
    imgFileList.ejs 图片显示模板
    
     <body>
    
     <h1>图片上传展示</h1>
    
     <p><img src="<%= imgShow%>" /></p>
    
     </body>
    

    相关文章

      网友评论

          本文标题:Express框架

          本文链接:https://www.haomeiwen.com/subject/cbkoxctx.html