登录
首页 >  数据库 >  MySQL

node入门

来源:SegmentFault

时间:2023-02-24 15:35:36 154浏览 收藏

小伙伴们对数据库编程感兴趣吗?是否正在学习相关知识点?如果是,那么本文《node入门》,就很适合你,本篇文章讲解的知识点主要包括MySQL、Cookie、Node.js、session、express。在之后的文章中也会多多分享相关知识点,希望对大家的知识积累有所帮助!

这即将是一篇很长很长的文章...

从一个简单的服务器开始

// server.js
const http = require('http')

const server = http.createServer(() => {
    console.log('原地转300圈并listen3000端口')
})

server.listen(3000)

首先在终端运行

const server = http.createServer((req, res) => {
    // 处理请求和响应
    console.log('原地转300圈并listen3000端口')
    res.write('lalala')
    res.end()
})

此时在终端运行

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    console.log(req.url)
    res.write('lalala')
    res.end()
})

此时控制台输出:

可获取请求路径的server

这里的

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    switch(req.url) {
        case '/1.html': 
        res.write('111')
        break
        case '/2.html': 
        res.write('222')
        break
        default: 
        res.write('404')
        break
    }
    res.end()
})

可响应请求路径的server

可响应请求路径的server(返回404)

发现可以响应请求了是不是很棒棒!

但是每次都使用

fs.readFile('文件名', (err, data) => {
    if (err) {
        // err的处理
        console.log(err)
    } else {
        // data的处理
        console.log(data.toString())
    }
})

这里之所以要使用

fs.writeFile('文件名', '内容', (err) => {
    console.log(err)
})

学习了

// server.js
const http = require('http')
const fs = require('fs')

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    const file_name = '/public' + req.url
    fs.readFile(file_name, (err, data) => {
        if (err) {
            res.write('404')
        } else {
            res.write(data)
        }
        res.end()
    })
    
})
server.listen(3000)
此处注意




    Document
11111



    
22222

然后对相应的路径进行访问:

可响应静态文件请求的server

啦啦啦可以直接访问文件啦!

这是和前端联系很紧密的一节

前端请求后端数据的常用的两种方式:GET和POST。GET的数据是放在url中,POST的数据不在url中。所以对这两种方式,后端需要不同的处理方式。

修改一下上节的1.html:



    
11111
用户:
密码:

一个很丑的get方式的表单

GET

对于GET方式,需要处理的是

// server.js
const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    res.write(req.url)
    res.end()
})
server.listen(3000)

点提交之后,来观察一下页面的变化:

一个很low的get方式的表单

emmmm...虽说这确实太不安全了,但是就先学习一下思路嘛...

对于

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    var get = {}
    var url = req.url
    if (url.indexOf('?') !== -1) {
        var arr = url.split('?')
        var arr1 = arr[1].split('&')

        for (let i = 0; i 
const queryString = require('querystring')

var query = queryString.parse('user=user&pass=123')
console.log(query) // { user: 'user', pass: '123' }

所以就可以使用这个模块来将处理方式变得简单点~

// server.js
const http = require('http')
const queryString = require('querystring')

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    var get = {}
    var url = req.url
    if (url.indexOf('?') !== -1) {
        var arr = url.split('?')
        get = queryString.parse(arr[1])
        res.write(JSON.stringify(get))
    }
    res.end()
})
server.listen(3000)

但是这里还需要

const urlLib = require('url')

var url = urlLib.parse('localhost:4000/?user=user&pass=123')
console.log(url)
// Url {
//     protocol: 'localhost:',
//     slashes: null,
//     auth: null,
//     host: '4000',
//     port: null,
//     hostname: '4000',
//     hash: null,
//     search: '?user=user&pass=123',
//     query: 'user=user&pass=123',
//     pathname: '/',
//     path: '/?user=user&pass=123',
//     href: 'localhost:4000/?user=user&pass=123' }

主要看的就是

const urlLib = require('url')

var url = urlLib.parse('localhost:4000/?user=user&pass=123', true)
console.log(url.query)//{ user: 'user', pass: '123' }

// server.js
const http = require('http')
const urlLib = require('url')

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    var obj = urlLib.parse(url, true) 
    var get = obj.query
    var url = obj.pathname
    res.write(JSON.stringify(get))
    res.end()
})
server.listen(3000)

POST

上面的一路看过来已经get到点了...所以来post一下。

先修改之前的1.html,将get方式改为post即可

用户:
密码:

因为post的数据是放在HTTP报文主体中的,数据获取就是一个很大的问题,所以首先看一下node怎么接收post数据。

node接收post数据主要是使用

req.on('data', (data) => {}) // 每次接收数据时触发
req.on('end', () => {}) // 接收完毕数据时触发

因为post数据可以很大,所以对较大的数据包会进行分块再处理。分块可以避免由于种种错误而产生的大块数据重新传输,会浪费资源。

const server = http.createServer((req, res) => {
    console.log('原地转300圈并listen3000端口')

    var post = ''
    req.on('data', (data) => {
        post += data
    })
    req.on('end', () => {
        res.write(JSON.stringify(post))
        res.end()
    })
})
server.listen(3000)

可以看到显示的数据是这样的;

一个打印出密码的post方式的表单

之所以要监听两个事件是因为POST数据较大时数据也是分块发送的,所以读者朋友可以试一下增加个

const queryString = require('querystring')

//...
req.on('end', () => {
    var POST = queryString.parse(post)
    res.write(JSON.stringify(POST))
    res.end()
})

一个简单的应用

呐呐...来应用一下噻,比如说制作一个注册登录的界面。目前因为没有应用到数据库,就可以直接使用存储几个账号密码的map来模拟一下~

具体代码可以看reg&login

接下来是express的部分~

express

使用之前应该先安装

// server.js
const express = require('express')

const server = express()
server.listen(3000)

emmmm...这个时候使用

server.use('/', (req, res) => {
    res.send('这是首页')
    res.end()
})

此时就会发现首页上有东西啦!

一个express启动的简易首页

express中的

const server = express()
server.get('/', (req, res) => {
    res.send('get到了')
    res.end()
})
server.post('/', (req, res) => {
    res.send('post到了')
    res.end()
})
server.listen(3000)

一个简易的get请求的express

而使用

server.use(express.static('public'))

有了上面一句之后就可以访问

server.get('/', (req, res) => {
    res.send(req.query)
    res.end()
})

就可以像下图一样:

一个打印出了密码的简陋express

所以具备了用express搞注册登录的基础知识,可以来一波实践哦~

express实现注册登录

代码可以见2-reg-login

express处理POST请求

上文学习了express使用

用户:
密码:

const bodyParser = require('body-parser')

server.use(bodyParser.urlencoded())
server.use('/', (req, res) => {
    res.send(req.body) // 使用了bodyParser之后body属性上才会有值
    res.end()
})

然后打开

server.use(bodyParser.urlencoded({
    extended: false,   
    limit: 2 * 1024 * 1024      // 限制2M
}))

这个时候就会发现上图中的提示没有了。

express的一些操作

链式操作

server.use('/', (req, res, next) => {
    console.log('a')
    // next()
})

server.use('/', (req, res) => {
    console.log('b')
})

如上述代码,当没有next时控制台只打印一个a,但是有了next之后,控制权可以交给下一个

server.use((req, res, next) => {
    req.on('data', )
})

server.use('/', (req, res, next) => {
    res.send(req.body) // 下方可以获取到
})

运行后如图:

自行添加的req.body

那么就可以模仿

server.use((req, res, next) => {
    var str = ''
    req.on('data', (data) => {
        str += data
    })
    req.on('end', () => {
        req.body = str
        next() // 注意这里next的位置
    })
})

server.use('/', (req, res, next) => {
    res.send(req.body)
})

还用之前那个1.html,结果如下图:

自己做的中间件

这时候想处理成json的话就可以用之前的querystring的parse。

依然是跟前端联系很紧密的一节

呐呐这次要了解的是cookie和session~

cookie设置和读取

可以在chrome浏览器F12 -> Application -> Cookies看到网页的cookie,可以使用

server.use('/', (req, res) => {
    res.cookie('user', 'oneday', {
        maxAge: 24 * 1000 * 3600 // 设置时间
    })
    res.send()
})

此时查看浏览器控制台就会发现有了这样一个cookie:

自己设置的1天后过期的cookie
不设置maxAge的话cookie会在浏览器关闭后失效。

也可以在

server.use('/', (req, res) => {
    res.cookie('user', 'oneday', {
        path: '/one', // 设置路径
    })
    res.send()
})

如果使用path属性设置了

const cookieParser = require('cookie-parser')

server.use(cookieParser())
server.use('/', (req, res) => {
    res.cookie('user', 'oneday', {
        path: '/one',
        maxAge: 24 * 1000 * 3600 
    })
    res.send(req.cookies) // 使用了cookie-parser中间件后才有的cookies属性
})

这时如果访问

server.use(cookieParser())
server.use('/', (req, res) => {
    req.secret = '愿所有的爱和付出都不会被辜负' // 签名密钥
    res.cookie('user', 'oneday', {
        maxAge: 24 * 1000 * 3600,
        signed: true
    })
    res.send(req.cookies)
})

可以看到如下图的输出:

签了名的cookie

可以看到该签了名的cookie很明显的将原始的cookie包含在了内容中,emmmm内容还是可以看到的。但是一旦cookie被修改了就能看得出来啊,所以签名只是能做到防篡改,不能做到直接加密。

签过名的cookie以

// 告诉cookieParser加密使用的字符串
server.use(cookieParser('愿所有的爱和付出都不会被辜负'))
server.use('/', (req, res) => {
    req.secret = '愿所有的爱和付出都不会被辜负' // 签名密钥
    res.cookie('user', 'oneday', {
        maxAge: 24 * 1000 * 3600,
        signed: true
    })
    res.send(req.signedCookies) // 就可以将签过名的cookie原样输出
})

原样输出cookie

删除cookie

删除cookie则是使用

const cookieParser = require('cookie-parser')
const cookieSession = require('cookie-session')

server.use(cookieParser())
server.use(cookieSession())

server.use('/', (req, res) => {
    res.send(req.session)
})

会发现报错了~~

一个报了错的session

呐呐来介绍一下这个keys。它的存在是为了预防session劫持的发生,keys是一个密钥数组,可以用来加密,express会循环使用密钥来加密cookie。

server.use(cookieSession({
    keys: ['one', 'day', 'oneday'] // keys加密数组,注意使用方法
}))

server.use('/', (req, res) => {
    if (req.session['count'] == null) {
        req.session['count'] = 1
    } else {
        req.session['count']++
    }
    console.log(req.session['count'])
    res.send('OK')
})

会发现每次控制台的session都会刷出来两个数字,那是因为也访问到了

server.use(cookieSession({
    name: 'ses',
    keys: ['one', 'day', 'oneday'],
    maxAge: 2 * 3600 * 1000 // 2小时
}))

session的删除

服务器端使用





    Document
    我的名字叫:

// ciews下ejs.js
const ejs = require('ejs')

ejs.renderFile("./views/index.ejs", {name: "oneday"}, (err, data) => {
    if(err) {
        console.log("编译失败")
    } else {
        console.log(data)
    }
})

使用

    
  • 不转义的字符串:
    server.set('views', './views')
    server.set('view engine', 'ejs')
    
    server.get('/index', (req, res) => {
        res.render('index.ejs', {name: 'oneday'})
    })

    文件上传

    这节主要讲怎么用express实现一个文件上传功能。

    将1.html内容进行更改:

    文件:

    const express = require('express')
    const bodyParser = require('body-parser')
    
    const server = express()
    
    server.use(bodyParser.urlencoded({extended: false}))
    server.post('/', (req, res) => {
        res.send(req.body)
    })
    
    server.listen(3000)

    此时运行一下试试会发现只打印出来了图片的名称,意思是只上传了文件名。原因是

    文件:

    const multer = require('multer')
    
    var objmulter = multer()
    const server = express()
    
    server.use(objmulter.any()) // 可以是single(指定的名称)
    
    server.post('/', (req, res) => {
        res.send(req.files)
    })

    这时再运行就会发现有很多buffers数据出来了...但是只要这样的数据肯定是没有什么用处的啊,毕竟我们要的是上传的文件嘛...那就可以像下面这样对数据进行一下处理:

    var objmulter = multer({dest: './www/upload'}) // 只改这一行代码,dest指定目标文件夹

    这是再运行会发现www/upload下面真的会有一个文件,但是是一个很长名字且没有后缀,也就是没有文件类型的一个文件,接下来我们要做的就是给它加一个文件扩展名,要用到一个叫

    const path = require('path')
    
    var str = "c:\\www\\aaa\\nbb.png"
    
    var obj = path.parse(str)
    console.log(obj)

    会发现输出如下:

    一个处理了路径的path包

    所以通过以下代码可以完成一个文件上传的小应用~

    const multer = require('multer')
    const pathLib = require('path')
    const fs = require('fs')
    
    var objmulter = multer({dest: './www/upload'})
    const server = express()
    
    server.use(objmulter.any())
    
    server.post('/', (req, res) => {
    
        var newName = req.files[0].path + pathLib.parse(req.files[0].originalname).ext
        // 重命名临时文件
        fs.rename(req.files[0].path, newName, (err) => { // fs.rename
            if (err) {
                res.send('上传失败')
            } else {
                res.send('上传成功')
            }
        })
    })

    选择文件并上传后,会发现在www/upload下是真的有该文件的,而且可以正常打开~

    数据库操作

    这里用到的数据库是mysql,管理工具是Navicat Premium。在node中需要首先

    const mysql = require('mysql')
    
    const db = mysql.createConnection({
        host: 'localhost', // 目标
        user: 'root',  // 用户名
        port: 3306,  // 端口号
        password: '123456', // 密码 
        database: 'user_table' // 数据库名
    })

    数据库操作语法统一格式为:

    -- INSERT INTO 表(字段列表) VALUES(值列表)
    INSERT INTO `user_table` (`username`, `password`) VALUES ('one', '123456')
    • 删-

    -- DELETE FROM 表名 (WHERE 条件)
    DELETE FROM `user_table` WHERE `username`='one'
    • 改-

    -- UPDATE 表名 SET 字段=值, 字段=值, 字段=值...(WHERE 条件)
    UPDATE `user_table` SET `username`='oneday', `password`='233333' WHERE `username`='one'
    • 查-SELECT

    -- SELELT (内容) FROM 表名 (WHERE 条件)
    SELECT * FROM `user_table`

    一些子句

    • where

    WHERE `age` >= 18
    WHERE `age` >= 18 AND `score`  100 OR `score` > 1000
    • order

    -- ASC -> 升序 | DESC -> 降序
    ORDER BY `age` ASC/DESC
    -- 按价格升序,随后再按销量降序,多条件排序就用逗号分隔
    ORDER BY `price` ASC, `sales` DESC
    • group

    -- 按班级计数
    SELECT `class`, COUNT(class) FROM `student_table` GROUP BY `class`
    -- 每个班级的平均分
    SELECT `class`, AVG(score) FROM `student_table` GROUP BY `class`
    -- 每个班级的最高分和最低分
    SELECT `class`, MAX(score), MIN(score) FROM `student_table` GROUP BY `class`

    今天关于《node入门》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表