node.js学习系列三之框架及其整合

node框架

上一篇主要介绍了node中常用的对象以及相关的api的使用,这个将介绍node中常用的框架,以及和其他技术的整合

Express

Express是针对于http模块开发的框架,用于简化web的开发

安装:

npm install --save express

简单使用例子

// 0. 安装
// 1. 引包
var express = require('express')

// 2. 创建你服务器应用程序
//    也就是原来的 http.createServer
var app = express()


// 在 Express 中开放资源就是一个 API 的事儿
// 公开指定目录
// 只要这样做了,你就可以直接通过 /public/xx 的方式访问 public 目录中的所有资源了
app.use('/public/', express.static('./public/'))

// 得到路径
// 一个一个的判断
// 以前的代码很丑
app.get('/about', function (req, res) {
  // 在 Express 中可以直接 req.query 来获取查询字符串参数这些参数被封装在一个对象中
  console.log(req.query)
  res.send('你好,我是 Express!')
})


// 当服务器收到 get 请求 / 的时候,执行回调处理函数
app.get('/', function (req, res) {
  res.send(`


  
    
    Document
  

  

hello Express!你好

`
) }) //当所有请求都不匹配的时候进入这个方法 app.use(function (req, res) { res.send('没有匹配的请求') }) // 相当于 server.listen app.listen(3000, function () { console.log('app is running at port 3000.') })

获取提交的参数

get请求

app.get('/about', function (req, res) {
  // 在 Express 中可以直接 req.query 来获取查询字符串参数这些参数被封装在一个对象中
  console.log(req.query);
})

post请求

在express中没有内置获取以post方式提交的请求数据,所以我们需要一个第三方的包body-parser.

安装:

npm install --save body-parser

使用例子:

var express = require('express')
//引包
var bodyParser = require('body-parser')
var app = express()

// 配置 body-parser 中间件(插件,专门用来解析表单 POST 请求体)
//只要加上这个配置,那么在req请求对象中就会多出一个body属性,在req.body中封装了post方式提交的数据
// parse application/x-www-form-urlencoded 如果提交的数据为form表单提交使用这个
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json 如果提交的数据以json格式提交使用这个
app.use(bodyParser.json())

app.post('/post', function (req, res) {
  var postData = req.body
})

app.listen(3000, function () {
  console.log('running...')
})

重定向

使用很简单:

app.post('/post', function (req, res) {
  // res.send
  // res.redirect
  // 这些方法 Express 会自动结束响应
  res.redirect('/')
})

路由

这里的路由其实很简单就是上面写的app.get(“url”,function(){})。其实就用于定义url于处理方法的对应关系的,这个就叫做路由。

但是如果我们直接在页面如果写路由那么页面就变的很乱,所以我们就需要使用模块化的概念,将路由抽取出到一个模块中。

路由模块

  • 职责:处理路由,根据不同的请求方法+请求路径设置具体的请求处理函数
  • 我们划分模块的目的就是为了增强项目代码的可维护性
  • 提升开发效率

不用express

app.js

var express = require('express')
var router = require('./router')

var app = express()

router(app);//调用router中的方法将app传到路由模块中

app.listen(3000, function () {
  console.log('running 3000...')
})

router.js

module.exports = function (app) {

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })

  app.get('/students/new', function (req, res) {

  })

  app.post('/students/new', function (req, res) {

  })
}

虽然这种方式可以实现对应的功能,但是这种方式一般不用。通常都是使用express中的封装好的方式

结合express

这个是最常用的方式

app.js

var express = require('express')
var router = require('./router')

var app = express()

// 把路由容器挂载到 app 服务中
app.use(router)

app.listen(3000, function () {
  console.log('running 3000...')
})

router.js

// Express 提供了一种更好的方式
// 专门用来包装路由的
var express = require('express')

// 1. 创建一个路由容器
var router = express.Router()

// 2. 把路由都挂载到 router 路由容器中
  router.get('/students/new', function (req, res) {

  })

  router.get('/students/new', function (req, res) {

  })

  router.get('/students/new', function (req, res) {

  })

  router.get('/students/new', function (req, res) {

  })

  router.post('/students/new', function (req, res) {

  })

// 3. 把 router 导出
module.exports = router

静态资源的访问

静态资源的访问有3中

var express = require('express')

// 1. 创建 app
var app = express()

// 当以 /public/ 开头的时候,去 ./public/ 目录中找找对应的资源
// 这种方式更容易辨识,推荐这种方式
// 例如:http://localhost/public/test.js 那么他就会去public目录下找test.js
app.use('/public/', express.static('./public/'))

// 必须是 /a/puiblic目录中的资源具体路径
// 例如:http://localhost/a/b/c/test.js 那么他就会去public目录下找/c/test.js
app.use('/a/b/', express.static('./public/'))

// 当省略第一个参数的时候,则可以通过 省略 /public 的方式来访问
// 这种方式的好处就是可以省略 /public/
// 例如:http://localhost/test.js 那么他就会去public目录下找/test.js
app.use(express.static('./public/'))

模板引擎的使用

这里主要介绍结合art-template模板引擎的使用,而art-template模板引擎是什么这个大家可以自己去百度一些资料很多,这个就不详细介绍了,因为这里主要还是说node.js

安装:

npm install --save art-template express-art-template

配置:

//第一个参数,表示,当渲染以 .art 结尾的文件的时候,使用 art-template 模板引擎
app.engine('art', require('express-art-template'))

使用

// Express 为 Response 相应对象提供了一个方法:render
// render 方法默认是不可以使用,但是如果配置了模板引擎就可以使用了
// res.render('html模板名', {模板数据})
// 第一个参数不写路径,默认会去项目中的 views 目录查找该模板文件
// 也就是说 Express 有一个约定:开发人员把所有的视图文件都放到 views 目录中
app.get('/', function (req, res) {
   //默认会去项目中的 views 目录查找index.art模板文件,然后使用第二个参数中的值替换模板中的数据
  res.render('index.art', {
    title: 'test'
  })
})
//如果想改默认查找模板的路径可以这样:
app.set('views', "模板查找路径")

例子:

var express = require('express')
var app = express()

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

// 配置使用 art-template 模板引擎
// 第一个参数,表示,当渲染以 .html 结尾的文件的时候,使用 art-template 模板引擎
// express-art-template 是专门用来在 Express 中把 art-template 整合到 Express 中
// 虽然这里不需要使用 art-template 但是也必须安装
// 原因就在于 express-art-template 依赖了 art-template
app.engine('html', require('express-art-template'))

app.get('/', function (req, res) {
  res.render('index.html', {
    name: 'test'
  })
})
//第二个参数可以没有
app.get('/post', function (req, res) {
  res.render('post.html')
})

app.listen(3000, function () {
  console.log('running...')
})

session的使用

在node中如果要使用session那么我们可以通过express-session模块来使用

安装:

npm install express-session

配置:

var session = require('express-session')

// 在 Express 这个框架中,默认不支持 Session 和 Cookie
// 但是我们可以使用第三方中间件:express-session 来解决
// 1. npm install express-session
// 2. 配置 (一定要在 app.use(router) 之前)
// 3. 使用
//    当把这个插件配置好之后,我们就可以通过 req.session 来发访问和设置 Session 成员了
//    添加 Session 数据:req.session.foo = 'bar'
//    访问 Session 数据:req.session.foo

app.use(session({
  // 配置加密字符串,它会在原有加密基础之上和这个字符串拼起来去加密
  // 目的是为了增加安全性,防止客户端恶意伪造
  secret: 'itcast',
  resave: false,
  saveUninitialized: false // 无论你是否使用 Session ,我都默认直接给你分配一把钥匙
}))

结合mongodb

在node中官方提供了mongodb包类操作mongodb数据库。不过为了更简单我们通常都是使用mongoose一个第三方的模块来操作mongodb数据库,还有就是mongoose也是对mongodb包的封装用于简化对于mongodb数据库的操作

简单的使用例子:

var mongoose = require('mongoose');

// 连接 MongoDB 数据库
mongoose.connect('mongodb://localhost/test', { useMongoClient: true });

mongoose.Promise = global.Promise;

// 创建一个模型(其实就是数据库),第一个参数是数据库名称,第二个是约束
// MongoDB 是动态的,非常灵活,只需要在代码中设计你的数据库就可以了
// mongoose 这个包就可以让你的设计编写过程变的非常的简单
var Cat = mongoose.model('Cat', { name: String });

for (var i = 0; i < 100; i++) {
  // 实例化一个 Cat(相当于表)
  var kitty = new Cat({ name: '喵喵' + i });

  // 持久化保存 kitty 实例
  kitty.save(function (err) {
    if (err) {
      console.log(err);
    } else {
      console.log('meow');
    }
  });
}

具体的使用

初始化

var mongoose = require('mongoose')

var Schema = mongoose.Schema

// 1. 连接数据库
// 指定连接的数据库不需要存在,当你插入第一条数据之后就会自动被创建出来
mongoose.connect('mongodb://localhost/itcast')

// 2. 设计文档结构(表结构)
// 字段名称就是表结构中的属性名称
// 约束的目的是为了保证数据的完整性,不要有脏数据
var userSchema = new Schema({
  username: {
    type: String,
    required: true // 必须有
  },
  password: {
    type: String,
    required: true
  },
  email: {
    type: String
  }
})

// 3. 将文档结构发布为模型
//    mongoose.model 方法就是用来将一个架构发布为 model
//    第一个参数:传入一个大写名词单数字符串用来表示你的数据库名称
//                 mongoose 会自动将大写名词的字符串生成 小写复数 的集合名称
//                 例如这里的 User 最终会变为 users 集合名称
//    第二个参数:架构 Schema
//   
//    返回值:模型构造函数
var User = mongoose.model('User', userSchema)

新增

// 4. 当我们有了模型构造函数之后,就可以使用这个构造函数对 users 集合中的数据为所欲为了(增删改查)
// **********************
// #region /新增数据.向users集合中新增
// **********************
var admin = new User({
  username: 'zs',
  password: '123456',
  email: '[email protected]'
})

admin.save(function (err, ret) {
  if (err) {
    console.log('保存失败')
  } else {
    console.log('保存成功')
    console.log(ret)
  }
})
// **********************
// #endregion /新增数据
// **********************

查询

// **********************
// #region /查询数据,向users集合中查询
// **********************
//查询所有
User.find(function (err, ret) {
  if (err) {
    console.log('查询失败')
  } else {
    console.log(ret)
  }
})
//根据条件查询
User.find({
  username: 'zs'
}, function (err, ret) {
  if (err) {
    console.log('查询失败')
  } else {
    console.log(ret)
  }
})
//根据条件查询一个
User.findOne({
  username: 'zs'
}, function (err, ret) {
  if (err) {
    console.log('查询失败')
  } else {
    console.log(ret)
  }
})
// **********************
// #endregion /查询数据
// **********************

删除

// **********************
// #region /删除数据 向users集合中删除
// **********************
//条件删除
User.remove({
  username: 'zs'
}, function (err, ret) {
  if (err) {
    console.log('删除失败')
  } else {
    console.log('删除成功')
    console.log(ret)
  }
})
// **********************
// #endregion /删除数据
// **********************

更新

// **********************
// #region /更新数据 向users集合中更新
// **********************
//根据id更新,第二个参数为要更新的值
User.findByIdAndUpdate('5a001b23d219eb00c8581184', {
  password: '123'
}, function (err, ret) {
  if (err) {
    console.log('更新失败')
  } else {
    console.log('更新成功')
  }
})
// **********************
// #endregion /更新数据
// **********************

结合mysql

结合mysql其实很简单,要使用mysql那么需要安装mysql模块

//导入mysql模块
var mysql = require('mysql');

// 1. 创建连接
var connection = mysql.createConnection({
  host: 'localhost',
  user: 'root',
  password: 'root',
  database: 'users'
});

// 2. 连接数据库 打开冰箱门
connection.connect();

// 3. 执行数据操作 把大象放到冰箱
connection.query('SELECT * FROM `users`', function (error, results, fields) {
  if (error) throw error;
  console.log('The solution is: ', results);
});

connection.query('INSERT INTO users VALUES(NULL, "admin", "123456")', function (error, results, fields) {
   if (error) throw error;
   console.log('The solution is: ', results);
 });

// 4. 关闭连接 关闭冰箱门
connection.end();

中间件

这里的中间件简单的说就类似于java中的拦截器。用于在请求的过程中拦截请求从而进入相应的方法中,进行处理。其实我们现在常用的app.get以及app.post也是中间件,中间件也叫路由。中间件:处理请求的,本质就是个函数方法,

该方法接收三个参数:
Request 请求对象、Response 响应对象、next下一个中间件

当请求进来,会从第一个中间件开始进行匹配如果匹配,则进来如果请求进入中间件之后,没有调用 next 则代码会停在当前中间件,如果调用了 next 则继续向后找到第一个匹配的中间件,如果不匹配,则继续判断匹配下一个中间件,一直不匹配就一直向后面找。所以 next 是一个方法,用来调用下一个中间件的。如果一直找不到能匹配的中间件,则 Express 会默认输出:Cannot GET|POST 路径

在express中间件有怎么几种:

  • use
    • 匹配所有类型的请求
  • get
    • 只匹配get类型的请求
  • post
    • 只匹配post类型的请求

例如:

var express = require('express')
var app = express()

//这个会匹配所有请求,然后输出1,进入这个请求之后就不会再向后面匹配其他的中间件了
app.use(function (req, res, next) {
  console.log('1')
})
//这个会匹配所有请求,然后输出1,由于调用了next()进入这个请求之后还会继续向后面匹配其他的中间件
app.use(function (req, res, next) {
  console.log('1')
  next()
})
/*这个会匹配所有类型的请求,但是只匹配url为http://localhost:3000/a 开头的请求,
并且如果加了next()方法就会继续向后面匹配其他的中间件,否则就不会向后面匹配其他的中间件了。
*/
/*还有如果请求的是http://localhost:3000/a/b/c 他也是可以匹配的。
然后再方法中通过req.url获取请求路径那么他获取的是/b/c 用于匹配的/a是会被省略的。
但是仅仅只有use才会这样,get和post他们对于路径是精确匹配的而且通过req.url也不会将/a 省略
*/
app.use('/a', function (req, res, next) {
  console.log('b')
})

//只有请求类型为get类型,并且请求的URL为http://localhost:3000/的时候才会被匹配,并且由于调用了next()所以还会继续向后面进行匹配
app.get('/', function (req, res, next) {
  console.log('/')
  next()
})

//只有请求类型为post类型,并且请求的URL为http://localhost:3000/的时候才会被匹配,并且由于调用了next()所以还会继续向后面进行匹配
app.post('/', function (req, res, next) {
  console.log('/')
  next()
})

app.listen(3000, function () {
  console.log('app is running at port 3000.')
})

注意

要匹配所有必须要use。如果用get或post必须要给匹配的路径,而next()3种方法都支持。还有代码的顺序是会影响匹配的顺序的。并且同一个请求中request对象是共享的

错误中间件

配置:

// 配置错误处理中间件,这4个参数必须写全
app.use(function (err, req, res, next) {
  res.status(500).send(err.message)
})

使用:

app.get('/', function (req, res, next) {
  fs.readFile('./the/path/nofile.txt', function (err, data) {
    if (err) {
      // 当调用 next 的时候,如果传递了参数,则直接往后找到带有 四个参数的应用程序级别中间件
      // 当发生错误的时候,我们可以调用 next 传递错误对象
      // 然后就会被全局错误处理中间件匹配到并处理之,通常在next中传递的是错误对象,当然传递其他的数据也是可以的
      next(err)
    }
  })
})

结语

到这里node.js的学习专栏就结束了,通过这些我相信入门node是没有问题的,当然node里面很多很多的对象以及api这个还需要各位用到的时候自己去官网看看哈,总之node他就是一个平台提供了js的另外一个运行环境,让js能够不再依赖于浏览器从而实现让他能够编写后台

你可能感兴趣的:(node.js学习)