Node.js学习(7)搭建服务器

原生服务器搭建

//1.引入http模块
let http = require('http')

//2.创建服务对象
let server = http.createServer((request,response)=>{
    response.end('<h1>hello,nodejs</h1>')
})

//3.绑定端口监听
server.listen(3000,(err)=>{
    if(!err){
        console.log('nodejs server 启动成功')
    }else{
        console.log(err)
    }
})

接收url参数

//1.引入http模块
let http = require('http')
let queryString = require('querystring')

//2.创建服务对象
let server = http.createServer((request,response)=>{
    let param = request.url.split('?')[1]
    let paramObj = queryString.parse(param)
    console.log(paramObj)
    response.setHeader("content-type","text/html;Charset=utf-8")
    response.end(`<h1>hello,${paramObj.username}</h1>`)
})

//3.绑定端口监听
server.listen(3000,(err)=>{
    if(!err){
        console.log('nodejs server 启动成功')
    }else{
        console.log(err)
    }
})

使用express搭建

安装express

yarn init
yarn add express

新建index.js,内容如下:

//1.引入express模块
let express = require('express')

//2.创建app应用对象
let app = express()

//3.设置路由
app.get('/',(request,response)=>{
    response.send('<h1>这是首页</h1>')
})
app.get('/meishi',(request,response)=>{
    response.send('<h1>这是美食页面</h1>')
})
app.get('/index',(request,response)=>{
    response.sendFile(__dirname+'/public/index.html')
})

//4.绑定端口监听
app.listen(3000,(err)=>{
    if(!err){
        console.log('express 服务器启动成功')
    }else{
        console.log(err)
    }
})

运行即可。

获取get参数

app.get('/',(request,response)=>{
    response.send('<h1>这是首页</h1>')
    console.log(request.query)
})

获取路由参数

app.get('/meishi/:id',(request,response)=>{
    response.send('<h1>这是美食页面</h1>')
    console.log(request.params.id)
})

获取请求头

console.log(request.get('user-agent'))

Express的Request对象属性和方法

Express的Response对象的属性和方法

中间件

概念

Express 是一个自身功能极简,完全是由路由和中间件构成一个的 web 开发框架:从本质上来说,一个 Express 应用就是在调用各种中间件。
中间件(Middleware) 是一个函数,它可以访问请求对象(request), 响应对象(response), 和 web 应用中处于请求-响应循环流程中的中间件,一般被命名为 next 的变量。

中间件功能

  • 1)执行任何代码。
  • 2)修改请求和响应对象。
  • 3)终结请求-响应循环。
  • 4)调用堆栈中的下一个中间件。

中间件的分类

  • 1)应用级中间件(过滤非法的请求,例如防盗链)
  • 2)第三方中间件(通过npm下载的中间件,例如body-parser)
  • 3)内置中间件(express内部封装好的中间件)
  • 4)路由器中间件 (Router)

中间件实例

let express = require('express')

let app = express()

app.use(express.urlencoded({extended: true}))  //解析post请求体的参数为一个对象,并挂载到request对象

//应用级(全局)中间件(第一种写法)
app.use((request, response, next) => {
    console.log('middleware')
    if (request.get('user-agent').includes('iPhone')) {
        response.send('please use android')
    } else {
        next()
    }
})

//应用级(全局)中间件(第二种写法)
function myMiddleWare(request, response, next) {
    console.log('my middleware')
    if (request.get('host') !== 'localhost:3000') {
        response.send('forbidden')
    } else {
        next()
    }
}

app.get('/foo', (request, response) => {
    response.send('foo')
})

app.get('/bar', myMiddleWare, (request, response) => {
    response.send('bar')
})

app.post('/foo', (request, response) => {
    console.log(request.body)
})

app.listen(3000, (err) => {
    if (!err) {
        console.log('express 服务器启动成功')
    } else {
        console.log(err)
    }
})

暴露静态资源

app.use(express.static('public'))  //暴露静态资源

如果没有暴露静态资源,则每次请求public目录下的静态资源都需要建立路由。
例如public目录下有一个index.html,如果需要通过http://localhost:3000/index.html访问该文件,则需要通过app.get的方式添加,如果设置了暴露静态资源,则不需要。

Router路由器

  • 概念
    Router是一个完整的中间件和路由系统,也可以看做是一个小型的app对象。
  • 作用

更好的分类管理route

  • Router的使用
    server.js内容如下:
let express = require('express')
let db = require('./db')
let loginReg = require('./router/loginReg')
let uiRouter = require('./router/uiRouter')

let app = express()

app.use(express.urlencoded({extended: true}))
app.use(express.static('public'))  //暴露静态资源

db.then(()=>{
    app.use(loginReg)
    app.use(uiRouter)
}).catch((err)=>{
    console.log(err)
})

app.listen(3000, (err) => {
    if (!err) {
        console.log('express 服务器启动成功')
    } else {
        console.log(err)
    }
})

router/loginReg.js文件代码内容如下:

let {Router} = require('express')
let userModel = require('../model/users')

let router = new Router()

router.post('/reg', (request, response) => {
    let body = request.body

    ;(async () => {
        // await db
        let user = userModel.findOne({user_name: body.username}, {_id: 0})
        if (await user) {
            response.send('<h1>该账号已注册</h1>')
        } else {
            let userId = makeUserId()
            await userModel.create({
                user_name: body.username,
                password: body.password,
            })
            response.send('<h1>创建账号成功</h1>')
        }
    })()
})

router.post('/login', (request, response) => {
    let body = request.body
    ;(async () => {
        let user = await userModel.findOne({user_name: body.username}, {_id: 0})
        if (user) {
            if (user.password != body.password)
                response.send('<h1>账号或密码错误</h1>')
            else
                response.send('<h1>' + body.username + '登录成功</h1>')
        } else {
            response.send('<h1>该账号未注册</h1>')

        }
    })()
})

module.exports = router

router/uiRooter.js文件代码内容如下:

let {Router} = require('express')
let {resolve} = require('path')
let router = new Router()

router.get('/login',(request,response)=>{
    let path = resolve(__dirname,'../public/login.html')
    response.sendFile(path)
})

router.get('/reg',(request,response)=>{
    let path = resolve(__dirname,'../public/reg.html')
    response.sendFile(path)
})

module.exports = router

后台服务启动

通过node xxx.js启动后,只要断开连接(Ctrl+C),那么服务也关闭了,如何让nodejs在服务器后台一直运行呢?这就需要用到forever这个包
目前最常见的线上部署nodejs项目的有forever,pm2这两种。
forever适合管理多个站点,每个站点访问量不大,不需要监控。
pm2适合网站访问量比较大,需要完整的监控界面。

forever项目地址:https://github.com/foreversd/forever

$ sudo npm install forever -g   #安装
$ forever start app.js          #启动
$ forever stop app.js           #关闭
$ forever start -l forever.log -o out.log -e err.log app.js   #输出日志和错误

常用命令:

forever start 你的脚本文件(如server.js)
forever list 查看所有 forever 运行的进程
forever stop uid 停止运行指定 uid 的进程

发送http请求

通过request模块可以模拟http请求

安装

yarn add request

使用

  • GET请求
var request = require('request');
request('http://www.baidu.com', function (error, response, body) {
  if (!error && response.statusCode == 200) {
    console.log(body) // Show the HTML for the baidu homepage.
  }
})
  • POST application/json
request({
    url: url,
    method: "POST",
    json: true,
    headers: {
        "content-type": "application/json",
    },
    body: JSON.stringify(requestData)
}, function(error, response, body) {
    if (!error && response.statusCode == 200) {
    }
}); 
  • POST application/x-www-form-urlencoded
request.post({url:'http://service.com/upload', form:{key:'value'}}, function(error, response, body) {
    if (!error && response.statusCode == 200) {
    }
})
  • POST multipart/form-data
var formData = {
    // Pass a simple key-value pair
    my_field: 'my_value',
    // Pass data via Buffers
    my_buffer: new Buffer([1, 2, 3]),
    // Pass data via Streams
    my_file: fs.createReadStream(__dirname + '/unicycle.jpg'),
};
request.post({url:'http://service.com/upload', formData: formData}, function (error, response, body) {
    if (!error && response.statusCode == 200) {
    }
})

如上所示,formData可以直接放key-value格式的数据,也可以放buffer,或者是通过流描述的文件。

发表评论

邮箱地址不会被公开。 必填项已用*标注