7_express

Express框架

首先我们先安装Node.js

0.基于express框架,创建项目。

创建工程目录

mkdir myNodeExpress01  
#创建项目
cd myNodeExpress01
#进入目录

通过npm init命令给你的应用创建一个package.json 文件。(包含工程的基本信息,以及工程模块的依赖列表)

npm init
#具体请看2_node NPM的使用。

在项目的根目录下安装Express并将其保存在依赖列表中。

npm install express --save

在项目的根目录下创建index.js文件,并在其中调用express 框架提供的方法,搭建web服务器。

//引入express模块
const express=require('express');

const webApp=express();
const port=2222;

// 根据不同的请求处理业务
webApp.get('/',(req,res)=>{
    res.send('这是我的第一个express 应用');
})
webApp.get('/login',(req,res)=>{
    res.send('这是我的的登录');
})

webApp.listen(port,()=>{
    console.log(`server is running at http://127.0.0.1:${port}`);
});

以上是使用express 搭建一个基本的Web服务器的代码示例.

1.快速入门

  npm提供了大量的第三方模块,其中不乏有许多web框架,之所以选择使用Express作为开发框架,因为他是目前最稳定,使用最广泛,而且Node.js官方推荐的唯一一个WEB开发框架。
  Express除了为http模块提供了更高层的接口外,还实现了许多功能,其中包括:

  • 路由控制
  • 模板解析
  • 动态视图
  • 用户会话
  • CSRF保护
  • 静态文件服务
  • 错误控制器
  • 访问日志
  • 缓存
  • 插件支持
      Express 不是一个无所不能的全能框架,他只是一个轻量级的web框架,多数功能只是对HTTP协议中常用的操作的封装,更多的功能需要插件或者整合其他模块来完成。

1.1 安装express

$ npm install -g express //全局安装

等待安装完成后,我们可以在命令行下通过express 命令快速创建一个项目。
在使用以下命令安装express-generator(应用构造器)

应用程序生成器:
我们可以通过npx 命令来安装express 应用程序生成器。

mkdir myNodeExpress02
cd myNodeExpress02
npx  express-generator

也可以使用npm 命令安装Express应用程序生成器

npm install -g express-generator
$ npm install express-generator -g 

1.2 建立工程&启动工程(使用express-generator应用构造器创建项目)

  通过以下命令建立网站的基本解构

$ express projectName
// projectName 要创建的项目名称

当前目录下会出现一个projectName的子目录,并且创建一些文件:

   create : projectName/
   create : projectName/public/
   create : projectName/public/javascripts/
   create : projectName/public/images/
   create : projectName/public/stylesheets/
   create : projectName/public/stylesheets/style.css
   create : projectName/routes/
   create : projectName/routes/index.js
   create : projectName/routes/users.js
   create : projectName/views/
   create : projectName/views/error.jade
   create : projectName/views/index.jade
   create : projectName/views/layout.jade
   create : projectName/app.js
   create : projectName/package.json
   create : projectName/bin/
   create : projectName/bin/www

    // 执行如下操作
   change directory:
     $ cd projectName   //进入项目的根目录

   install dependencies:
     $ npm install    //安装项目需要的依赖

   run the app:
     $ DEBUG=projectname:* npm start  //启动项目

  项目启动后,在浏览器输入http://localhost:3000,访问项目。

1.3 工程结构

1.3.1 app.js 和入口文件

app.js 是工程的配置文件,


var createError = require('http-errors');
// http错误处理模块
var express = require('express');
// express 模块
var path = require('path');
var cookieParser = require('cookie-parser');
// cookie 模块
var logger = require('morgan');
// 日志模块

// 引入的路由模块
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// 视图引擎的设置
app.set('views', path.join(__dirname, 'views'));
// 设置视图目录
app.set('view engine', 'ejs');
// 设置模板引擎  官方提供了jade ,ejs;ejs 更接近于HTML语法,推荐使用

app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// 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;

./bin/www 是工程的入口文件。


// 以下文件内容相较于实际项目有缩减
/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('projectname:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 * 创建web服务器
 */


var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 * 添加web 服务器端口监听
 */

server.listen(port,function(){
  console.log('server is running ,port is '+port);
});


1.3.2 public 静态资源目录

  public中存放站点所需要的静态资源,比如图片,css,js,font等
配置静态资源目录,进入app.js 文件,使用以下代码:

// 静态资源目录的配置 静态资源挂载
app.use('/static',express.static(path.join(__dirname, 'public')));//给静态资源设置虚拟目录
app.use(express.static(path.join(__dirname, 'public')));//默认
1.3.3 views 视图(ejs模板)目录

   此目录下存放视图文件。

1.3.4 routes 路由文件目录

   此目录下存放路由文件。

2. 路由控制

  路由是为了处理不同的请求(url)执行的不同的操作。
我们要为路由提供请求的URL和其他需要的GET,POST,以及参数,之后路由需要根据这些数据来执行相应的代码。

2.1 工作原理

  express 是一个典型的MVC架构,浏览器发起请求,有路由控制器接受,根据不同的路径定向到不同的控制器,控制器处理用户的具体请求(具体业务),可能会访问数据库中的对象,即模型部分。控制器还要访问模板引擎,生成视图HTML,最后再由控制器返回给浏览器,完成一次请求。

2.2创建路由规则

  在routes/index.js 文件中,有个已有的路由规则 router.get('/',function(){});

router.get('/',function(req,res){
    res.send('123332132123132123');
})

2.3路径匹配规则

//router.get('/a/:parm1/:parm2');
// http://localhost:3000/a/parm1_val/parm2_val
// 取值时,使用req对象中的params对象取值。
router.get('/a*/:username',function(req,res){
    res.send('参数:'+req.params.username);
})

  路径规则/a/:username会被自动编译为正则表达式.路径参数可以在响应函数中通过req.params 的属性访问。

2.4 REST风格的路由规则

  Express 支持REST风格的请求方式,REST(表征状态转移Representational State Transfer),它是一种基于HTTP协议的网络应用的接口风格,利用HTTP的方法实现统一风格接口的服务。HTTP协议定义了以下8中标准的方法:

  • GET:请求获取指定资源(获取数据);
  • HEAD:请求指定资源响应头 (获取响应头信息);
  • POST:向指定的资源提交数据(发送数据);
  • PUT:请求服务器存储的一个资源 (存储数据);
  • DELETE:请求服务器删除指定资源 (删除数据);
  • TRACE:回显服务器收到的请求,主要用于测试或者诊断
  • CONNECT:HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
  • OPTIONS:返回服务器支持的请求方法。
    我们最常用的是GET,POST,PUT 和DELETE 方法。根据REST设计模式,这4种方法通常分别用于实现以下功能:
  • GET:获取
  • POST:新增
  • PUT:更新
  • DELETE: 删除
      Express 对每种HTTP请求方法都设计了不同的路由绑定函数。
请求方式 绑定函数
GET app.get(path,callback)
POST app.post(path,callback)
PUT app.put(path,callback)
DELETE app.delete(path,callback)
PATCH app.patch(path,callback)
TRACE app.trace(path,callback)
CONNECT app.connect(path,callback)
OPTIONS app.options(path,callback)
所有方法 app.all(path,callback)

  需要注意的是app.all函数,它支持把所有的请求方式绑定到同一个响应函数。

2.5 控制权转移

//routes/user.js
var users={ 
    username:'huskyuncle',
    password:'123456' 
}
router.all('/:username',function(req,res,next){
  // 检查用户是否存在
  if(users['username']==req.params.username){
    // 用户存在 
    next();
  }else{
    next(new Error(req.params.username+' 找不到数据'));
  }
})
router.get('/:username',function(req,res){
  // 用户存在,直接展示用户数据 
  res.send(JSON.stringify(users['username']+users['password']));
})

  router.all定义的这个路由规则实际上起到了中间件作用,把相似的请求的相同部分提取出来,有利于代码维护其他next方法如果接受了参数,也就代表发生错了,这种方式可以把错误检查分段化,降低代码的耦合度。

3. 模板引擎

  模板引擎(Template Engine)是一个从页面模板根据一定的规则生成HTML的工具。
  Express 内置ejs和jade 两种模板引擎(建议使用ejs),我们在Express框架中使用时,在app.js中通过以下语句设置了模板引擎和页面模板的位置:

app.set('views',__dirname+'/views');//设置页面模板位置
app.set('views engine','ejs');//设置使用的模板引擎

渲染页面时,我们在响应对象函数中使用res.render()渲染模板

router.get('/',function(req,res){
    // render(viewName,viewData);
    // *viewName 视图名称
    res.render('index',{data:'数据'});
})

ejs的标签系统,常用三种标签

  • <% code %> JavaScript代码
  • <%= code %> 显示替换过HTML特殊字符的内容|输出变量内容
  • <%- code %> 显示原始的HTML内容
  • <%- include('common/header',data); %> 在模板页中引入另外一个模板页,并且传输data参数给指定的模板页面(common/header)。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,639评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,277评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,221评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,474评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,570评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,816评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,957评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,718评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,176评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,511评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,646评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,322评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,934评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,755评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,987评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,358评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,514评论 2 348

推荐阅读更多精彩内容

  • 日精进打卡 姓名:张通明 公司:宁波普锐明汽车零部件有限公司 【日精进打卡第38天】 【知~学习】 1.学习“活法...
    d5be29eb948d阅读 106评论 0 0
  • 二十几岁。本该是七八点钟的朝阳,朝气蓬勃,意气风发。你却感到迷茫,前路漫漫,何处是远方? 无论你是大学生还是刚入职...
    我的老师是只猫阅读 2,734评论 7 18
  • 提起李清照,很多人脑海里便浮现出一个柔弱多情,才华横溢,婉约清丽的形象。 然而,她却吟得出“生当作人杰,死亦为鬼雄...
    沧笙踏歌Yolanda阅读 578评论 0 5
  • 感赏自己认真工作一天,感赏自己练车有进步心里很高兴。感赏自己得到领导的信任安排我明天去开会。感赏自己给儿子买到了想...
    冯梅fm阅读 262评论 0 3
  • 【日文】精通の目的は応用にある (せいつうのもくてきはおうようにある) 【中文】精通的目的在于应用 【感悟】...
    行禅者阅读 260评论 0 0