// 导入http模块
const http = require('http')
// 创建web服务器
const server = http.createServer()
//为服务绑定一个request事件
server.on('request', function(req, res){
//客户端请求地址
const url = req.url
// 设置访问某人响应
let content ='\<h1>404 not found!\</h1>'
//req.method客户端请求method
const method = req.method;
console.log(method, 'debugMethod')
if(url === '/'){
content='\<h1>首页\</h1>'
}
//防止中文乱码问题
res.setHeader('Content-Type', 'text/html; charset=utf-8');
// 响应内容,并结束响应过程
res.end(content)
})
// 启动服务器 server.listen(8080, ()=>{ console.log('服务启动了。。。。') }) node中的模块作用域
- 模块作用域的好处是防止全局污染
- moudule对象包含所有信息,moudule.exprots可以共享某块信息
- require方法导入某块时,导入的结果永远以module.exports
- CommonJs规范是nodejs规范,module代表当前模块,mould.expots是对外接口,使用rqurie()加载模块 npm包是封装出来的
- 包共享平台https//wwww.npmjs.com
- 共享包https//registry.npmjs.org/
- npm i 包名称 cls清空终端
- npm i @版本号下载版本号
- package.json包管理文件
- .gitigore中的文件忽略上传
- npm init -y 快速创建package.json
- dependencies节点,用来记录npm install命令安装了那些包
- npm i 安装多个包时使用空格隔开
- npm uninstall卸载包
- devDependencies只标记测试环境使用install -i 包名 -D
- 检查下班镜像源 npm confing get registry
- 切换镜像源 npm config set registry='registry.npm.taobao.org/'(镜像地址)
- nrm 镜像包管理工具 npm ls nrm use
- 包分类i5ting_toc把md文件转化为html文件
模块加载机制
- 如果模块已经在缓存中,将不会再进行加载
- 内置加载模块优先级最高
- 使用require导入自定义模块时,如果省略扩展名,node会按照确切文件名加载,没有会补全js加载,没有会补全.json,没有会补全node,都没有会直接加载失败
- 第三方模块加载机制,加载顺序--->当前文件加载---->然后往上逐一加载
express expressjs.com.cn快速搭建服务器
//导入express
const express = require('express');
//创建服务器
const app = express()
//监听get请求
// app.get('/user', (req,res)=>{
// //调用express提供的res.send方法,向客户端响应一个JSON对象
// res.send({name:'zhangsan', age:'28', gender:'男'})
// })
// //监听pos请求
// app.post('/user',(req,res)=>{
// res.send('请求成功')
// //调用express提供的res.send方法,向客户端响应一个文本
// })
// app.get('/', (req, res)=>{
// //通过req.query 响应客户端发送过来的查询参数
// //默认req.query是个空对象
// console.log(req.query, 'debug')
// res.send(req.query)
// })
// app.get('/user/:id',(req, res)=>{
// //动态匹配导的URL,默认是一个空对象
// console.log(req.params)
// res.send(req.params)
// })
//调用express.static()方法提供静态资源,多次调用express.static()只会调用第一个使用
app.use(express.static('./eatWhat'))
//需要访问是需要加个前缀
app.use('/eatWhat' ,express.static('./eatWhat'))
//启动服务器
app.listen(80, ()=>{
console.log('express server running at http://127.0.0.1')
})
nodemon 自动更新代码是否发生变化npm install -g nodemon
express路由
- express中的路由只是的客户端请求和服务器处理函数之间的映射关系
- 路由的匹配逻辑是从上往下匹配
- 路由中间键是依次处理的顺序,通过next()来实现函数调用
- 使用qpp.use()的是全局中间键,不使用app.use()的局部中间键
const app = express()
//定义一个最简单的
const mw = ((req,res, next)=>{
console.log('这是一个最简单的中间键函数')
// 全局挂载时间
const time = Date.now()
req.startTime =time
//把流转关系转交给下一个中间键或路
next()
})
//将mw注册成全局中间键
app.use(mw)
app.get('/',(req,res)=>{
res.send('hello world!')
})
app.post('/',(req,res)=>{
res.send('Post hello world!')
})
app.listen(80 ,()=>{
console.log('http://127.0.0.1');
})
局部
const express = require('express')
const app = express();
const mw = (req,res , next)=>{
console.log('局部生效中间键')
next()
}
//
app.get('/user',mw,(req, res)=>{
res.send('hello user get')
})
app.post('/name',(req, res)=>{
res.send('hello user post')
})
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
- 多个局部中间键使用逗号隔开从左往右执行,一定在路由之前注册中间键,最后需要使用next()
- 绑定在app实例上的都是应用级别
- express.router绑定在router身上的中间键都是路由级别的中间键
- 错误级别的中间键必须有4个参数
const express = require('express')
const app = express()
app.get('/usr',(req,res)=>{
//抛出错误
throw new Error('服务发生内部错误')
res.send('Home page')
})
//注册错误中间键
app.use((err,req,res,next)=>{
console.log(err.message + '错误信息')
res.send('err:' + err.message)
next()
})
app.listen(80,(req, res)=>{
console.log('http://127.0.0.1/');
})
- app.use(express.json())解析JSON数据
- app.use(express.urlenCoded({extended: flase}))
const express = require('express')
const app = express();
//Json数据机械除错误中间键其余都需要路由前配置
app.use(express.json())
//解析urlencoded数据
app.use(express.urlencoded({extends: false}))
app.post('/name',(req, res)=>{
// 获取前端数据
console.log(req.body)
res.send('hello user post')
})
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
- 使用第三方定义中间键
const express = require('express');
const app = express()
app.post('/user',(req,res)=>{
console.log(req.body)
res.send('hello post')
})
//导入第三方body-parser
const parser = require('body-parser')
app.use(parser.urlencoded({extended: false}))
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
- 自定义中间捷
const express = require('express')
const app = express();
//导入querystring模块
const qs = require('querystring')
//定义全局中间键
const mv = (req,res,next)=>{
//定义存储客户端发送请求数据
let str ='';
// 监听req的data事件
req.on('data',(chunk)=>{
str +=chunk
})
//监听end事件
req.on('end', ()=>{
// 在str中存储完整的请求体数据
console.log(str)
//把字符串请求体数据解析成对象格式
const body = qs.parse(str)
console.log(body)
req.body= body
next()
})
}
app.use(mv)
app.post('/name',(req, res)=>{
res.send(req.body)
})
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
- 使用node服务对外api接口
const app = express();
app.use(express.json())
app.use(express.urlencoded({extends: false}))
//导入路由
const router = require('./router/router');
//注册路由到app上
app.use('/api', router)
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
封装路由
const express = require('express');
//创建一个路由模块
const router = express.Router();
//挂载具体路由
router.get('/get', (req, res)=>{
console.log('deebug');
//通过客户端查询发送服务器数据
const query = req.query
//调用res.send()方法,向客户端发送
res.send({
status: 0, //0表示数据处理成功
mag: 'GET 数据请求成功',
data: query //响应客户端数据
})
})
//挂载具体路由
router.post('/post', (req, res)=>{
//通过客户端查询发送服务器数据
const body = req.body
//调用res.send()方法,向客户端发送
res.send({
status: 0, //0表示数据处理成功
mag: 'Post 数据请求成功',
data: body //响应客户端数据
})
})
//导出路由
module.exports = router
解决api接口跨域问题
- cors主流解决方案 npm i cors
const express = require('express')
const app = express()
//导出cors中间键
const cors = require('cors');
//配置cors中间键
app.use(cors)
app.listen(80,()=>{
console.log('http://127.0.0.1')
})
只允许某一个跨域共享access-control-allow-oringin配置
2. jsonp只支持get解决
//JSONP定义接口并实现
use.get('/api/jsonp',(req,res)=>{
//获得函数
const funName = req.query.callback
//定义向客户端发送数据对象
const data = {name:'zs', age:19,}
//拼接函数调用
const scriptStr = `${funName}(${JSON.stringify(data)})`
res.send(scriptStr);
})
MySQL数据库
- 查
- select * from my_db_node.users limit 10
- 增加数据
- insert into users (username, passworld, status) values ('aww','789',1)
- 改
- update users set status=1 ,passworld='567' where username='zs'
- 删除
- delete from users where id=2
- and和or
- select * from my_db_node.users where status='0' and id<3
- select * from my_db_node.users where status='0' or id=3
- 升序
- select * from users order by id
- 降序
- select * from users order by id desc
- 多重排序
- select * from users order by id desc, username asc
- count 和 as的作用统计和另取名
- select count(username) as uv from users
node操作MySQL 链接数据库
const mysql = require('mysql')
//创建mysql链接
const db = mysql.createPool({
host: '127.0.0.1',//数据库存放地址
user: 'root', //登录数据库账号
password: 'admin123', //登录密码
database: 'my_db_node' //操作数据
})
- 检测数据库是否成功
//检查数据是否链接
db.query('select 1', (err, results)=>{
//错误返回
if(err) return console.log(err.message);
//成功执行
console.log(results)
})
- 查询数据
//调用数据库
const sqlSelect = 'select * from users'
db.query(sqlSelect, (err, results)=>{
//错误返回
if(err) return console.log(err.message);
//成功执行,结果返回为数组
console.log(results)
})
- 数据插入
//新增数据
const user = {username: 'zz', password: 'main123'}
const sqlAdd = 'insert into users(username, passworld) values(?,?)'
//执行sql
db.query(sqlAdd,[user.username, user.password],(err, results)=>{
// 数据插入失败执行结果
if(err) return console.log(err.message);
//数据插入成功返回是对象,可以通过affectedRows判断是否成功
if(results.affectedRows ===1){
console.log('数据插入成功');
}
})
- 便捷写法
//新增数据
const user = {username: 'zzj', passworld: 'main123'}
// const sqlAdd = 'insert into users(username, passworld) values(?,?)'
//简化写法
const sqlAdd= 'insert into users set ?'
//执行sql
db.query(sqlAdd, user ,(err, results)=>{
// 数据插入失败执行结果
if(err) return console.log(err.message);
//数据插入成功返回是对象,可以通过affectedRows判断是否成功
if(results.affectedRows ===1){
console.log('数据插入成功');
}
})
- 数据更新
const user = { status: 1, passworld: '7123', username: 'zzj'}
const updatas = 'update users set status=? ,passworld=? where username=?'
db.query(updatas, [user.status, user.passworld, user.username ],(err, results)=>{
console.log('111')
if(err) return console.log(err.message);
//数据插入成功返回是对象,可以通过affectedRows判断是否成功
if(results.affectedRows ===1){
console.log('数据更新成功');
}
})
- 便捷方式
const user = { status: 0, passworld: '711', username: 'zzj'}
const updatas = 'update users set ? where username=?'
db.query(updatas, [user, user.username ],(err, results)=>{
console.log('22')
if(err) return console.log(err.message);
//数据插入成功返回是对象,可以通过affectedRows判断是否成功
if(results.affectedRows ===1){
console.log('数据更新成功');
}
})
- 删除数据,生成环境中不建议删除数据
//删除数据
const user = { status: 0, passworld: '711', username: 'zzj'}
const sqlDelete = 'delete from users where username=?'
db.query(sqlDelete, [user.username ],(err, results)=>{
if(err) return console.log(err.message);
//数据插入成功返回是对象,可以通过affectedRows判断是否成功
if(results.affectedRows ===1){
console.log('数据删除成功');
}
})
web前端的身份认证
- session认证,一般在服务端验证,由后端发送终端,一般不超过4kB的cookie,cookie的特性自动发送,域名独立,过期时限,4k限制,cookie不具有安全性,需要session认证
- JWT最常见的认证机制,组成有三部分Heade/payload/signatuer,放在authization 项目中使用session
npm i express-session
- 配置session
const express = require('express')
const app = express()
//创建服务器session
const session = require('express-session');
//配置session
app.use(session({
secret:'item',
resave: false,
saveUninitialized: true,
}))
app.listen(80,()=>{
console.log('https://127.0.0.1')
})
验证是否登录
// 判断用户是否登录
app.post('/login',(req, res)=>{
req.session.user = req.body //用户信息
req.session.islogin = true //用户登录状态
res.send({status:0, msg: '登录成功'})
})
// 判断用户是否登录
app.get('/login/name',(req, res)=>{
if(!req.session.islogin){
return res.send({status:1 , msg: 'fail'})
}
res.send({
status: 0,
msg: 'success',
username: req.session.user.username
})
})
用户清空session
//判断用户是否清空session
app.post('/login/out',(req, res)=>{
//清空登录方法
req.session.destroy()
res.send({status:0, msg: '退出登录成功'})
})
生成token
app.post('/username', (req, res)=>{
//将前端数据传递到userinfo
const userinfo = req.body
//登录失败
if(userinfo.username !== 'admin' || userinfo.password !== '000000'){
return res.send({
status: 400,
message: '登录失败'
})
}
//登录成功调用jwt方法
//配置对象秘钥,配置token有效期
const tokenStr = jwt.sign({username: userinfo.username}, secretKey, {expiresIn:'80s'})
//登录成功
res.send({
status:200,
massage: '登录成功',
token: tokenStr, //给客户端发送请求
})
})
- JWT最常见的认证机制校验token
const express = require('express')
//导入jsWeb
const Jwt = require('jsonwebtoken');
//导入jwt
const expressJwt = require('express-jwt')
const app = express()
//定义想秘钥
const secretKey = 'luckyJian'
//注册解析还原中间键,unless设置是否需要访问权限
app.use(expressJwt({secret: secretKey}).unless({path: [/^\/api\//]}))
app.post('/api/username', (req, res)=>{
//将前端数据传递到userinfo
const userinfo = req.body
//登录失败
if(userinfo.username !== 'admin' || userinfo.password !== '000000'){
return res.send({
status: 400,
message: '登录失败'
})
}
//登录成功调用jwt方法
//配置对象秘钥,配置token有效期
const tokenStr = Jwt.sign({username: userinfo.username}, secretKey, {expiresIn:'80s'})
//登录成功
res.send({
status:200,
massage: '登录成功',
token: tokenStr, //给客户端发送请求
})
})
// 验证是否登陆成功
app.get('admin/user',(req,res)=>{
console.log(req.user)
res.send({
status: 200,
message: '用户信息获取成功',
data: req.user
})
})
// 捕获错误
app.use((err,req,res,next)=>{
if(err.name === 'UnauthorizedError'){
return res.send({
status: 401,
massage: '无效token'
})
}
res.send({status:500,
massage: '未知错误'
})
})
app.listen(80,()=>{
console.log('https://127.0.0.1')
})