shift + 右键 + 点击打开PowerShell
打开终端自动定位到打开路径
Nodejs
安装apache
用于php
创建服务器了解即可
- 下载–>解压
Apache/conf/httpd.conf
中的Define SRVROOT "D:\Apache\Apache24"
改为Define SRVROOT "Apache24的完全路径"
httpd -k install -n Apache2.4
#-n后面表示自定义访问名称bin
目录下管理员启动cmd
httpd -k start
启动httpd -k stop
关闭httpd.exe
启动ctrl+c
关闭
- 直接双击
httpd.exe
程序启动 - 关闭
httpd.exe
程序关闭 - 浏览器输入
localhost
访问
终端命令
- 切换路径
cd
- 执行js文件
node 文件名
- 自动补全文件名
node 文件名开头+tab
- 清空当前行输入内容
esc
- 关闭当前行
ctrl+c
- 清屏
cls
fs文件系统模块
- 引入
fs
模块require('fs')
- 读取文件
readFile(path[,option],callback(err,data))
- 写入文件
writeFile(path,data[,option],callback(err))
- 写入内容会替代原来内容
- 文件不存在自动创建
__dirname
文件当前所处目录path
一般写成path.join(__dirname , '/xx/xx...')
- 如果用
./
或../
有时会出现拼接出错变成xxx./xx/xx
//引入fs模块
const fs = require('fs')
//读取
fs.readFile('./text/01test.text', 'utf8', function (error, data) {
console.log(error, '-----', data)
})
//写入
fs.writeFile('./text/01test.text', '写入内容', function (error) {
console.log(error)
})
/*成功err为null*/
path模块
- 引入
path
模块require('path')
- 拼接路径
path.join(__dirname , 'xx/x/x' , 'x/x/x')
(路径都推荐这样写) - 获取路径中的文件名
path.basename(url)
- 获取路径的扩展名
path.extname()
http模块
- 引入
http
模块require('http')
- 创建服务器实例
http.createServer()
- 为服务器绑定事件
server.on('事件名',callback(request,response))
request
,response
分别为请求对象与响应对象request.url
请求路径request.method
请求类型response.end()
响应数据response.setHeader('Content-Type','text/html; charset=utf-8')
设置响应头,解决乱码
- 监听端口
server.listen(端口号,callback())
//导入http模块
const http = require('http')
//创建web服务器实例
const server = http.createServer()
//为实服务器绑定事件,监听客户端请求
server.on('request',function(request,response){
console.log('有人访问')
})
//监听端口
server.listen(8080,()=>{
console.log('服务器启动咯')
})
向服务器请求页面实例
const fs = require('fs')
const path = require('path')
const http = require('http')
const app = http.createServer()
app.on('request', (request, response) => {
let url = request.url
let fpath = path.join(__dirname, url)
// response.setHeader('Content-Type','text/html;charset=utf-8')//加了这行相当于以后请求的所有内容格式utf8
fs.readFile(fpath, 'utf8',(error, data) => {
response.end(data)
})
})
app.listen(5000, () => {
console.log('服务器启动')
})
当客户端解析
html
时,发现其他路径的引用如css
,会再次向服务器发送请求
模块化
commonJs规范
module对象
- 每个模块里都有一个
module
对象存储了当前模块的信息 module.exports
对象- 外部
require
引用模块时,引用的是module.exports
对象
- 外部
exports对象
module.exports===exports
//ture
最后导出以
module.exports
为准
npm与包
认识与使用
- 安装包后会统一放在
node_models
文件夹中 npm i xxx@版本号
之前先npm init -y
创建package.json
文件一下,不然有可能不是安装在当前目录- 版本号规范
4.22.3
大版本号.功能版本号.bug修复版本号- 前面的数字更新,后面的数字清零
- 安装所有项目所依赖包
npm i
,全局-g - 卸载指定包
npm uninstall xxx
,全局-g
全局包默认安装路径C:\Users\用户目录\AppData\Roaming\npm\node_modules
- 把安装的包记录在
devDependencies
节点,代表项目开发时用,但是上线后不使用的包npm i xxx -D
完整写法--save-dev
package.json
内的字段意义dependencies
核心依赖包:开发上线都需要用的包-SdevDependencies
开发依赖包:开发用上线不用-D
- 查看获取包的服务器/获取当前包的镜像源
npm config get registry
- 安装淘宝镜像
npm config set registry=http://registry.npm.taobao.org/
- 每隔10分钟将海外
npm
服务器上的包拷贝到国内服务器解决下载慢的问题
- 每隔10分钟将海外
- 将nrm安装为全局工具
npm i nrm -g
- 查看所有可用镜像源
nrm ls
- 切换镜像源
nrm use taobao
- 包的
package.json
文件里必须包括三个属性:name
包名,version
版本号,main
包的入口- 详细
https://yarnpkg.com/zh-Hans/docs/package.json
- 详细
常用包
i5ting_toc
将.md
文档转化为html
i5ting_toc -f 路径 -o
nodemon
自动重启服务器
制作并发布自己的包
- 创建文件夹
xuzhou_tools
- 文件夹内创建三个文件
index.js
入口文件README.md
说明文件package.json
{
"name": "xuhzou_tools",//包名
"main": "./index.js",//入口文件
"version": "1.0.0",//版本号
"description": "实验我自己的包",//描述
"keywords": [//搜索关键子"xuzhou","tools"],
"license": "ISC"//开源协议
}
npm login
登录自己的npm
账号npm publish
发布包到npm
官网
登录账号要镜像源要切换到官网
发布时候要切到包目录下
npm unpublish
包名--force
删除包:只能删除72小时以内发布的包
模块化加载机制
- 自定义模块加载机制
require()
引入自定义模块时必须要加./或…/不然会优先引入内置模块再第三方模块,- 省略文件后缀如果找不到指定文件,会优先执行同名
.js
文件再.json
最后.node
最最后报错
- 第三方模块加载机制
- 逐级向上找
node_module
文件夹
- 逐级向上找
- 目录加载机制
- 先找
package.json
文件中的main
属性指定入口文件 - 如果没有
package.json
文件,执行index.js
文件
- 先找
express框架
对http
模块的封装
基本使用
- 安装
npm i express
- 导入模块
const app = require('express')
app.get(url,callback(request,response))
request.query
默认为空{}包含用户传递而来的query
参数127.0.0.1:8080/?id=2&de=s
客户端请求
request.params
默认为空{}包含用户传递而来的params
动态参数127.0.0.1:8080/xz/xs
客户端请求
response.send()
向服务端发送响应数据
app.post()
同理
//导入模块
const express = require('express')
const app = express()
app.get('/',(request,response)=>{
response.send(request.query)
})
app.post('/:name/:age',(request,response)=>{
response.send(request.params)
})
//对外托管静态资源
app.use(express.static('./text'))//路径前缀可空
//启动服务器
app.listen(8080,()=>{
console.log('服务器启动')
})
静态资源
app.use('路径前缀如/page',express.static(url))
对外托管静态资源127.0.0.1:8000/路径前缀/url下有的文件
- 对外托管多个静态资源就多用几次
app.use(express.static(url))
- 如果各个目录里有同名文件,按托管先后顺序向外托管
路由模块化
- 一般把挂载路由的步骤单独写在一个
js
文件里 - 再在启动服务器
js
文件中注册路由
const express = require('express')
//创建路由实例对象
const router = express.Router()
//挂载路由
router.get('/',(request,response)=>{
response.send(request.query)
})
//导出
module.exports=router
//启动服务器js文件中注册路由
const router = require('./路由独立模块')
app.use('路由前缀',router)
中间件
应用级别中间件
- 全局中间件
- 在匹配路由之前都需要通过全局中间件
//注册全局中间件
app.use((req,res,next)=>{
console.log('中间件被调用啦')
next()
})
- 所有全局中间件共享一份
request
和response
- 全局中间件按定义顺序执行
- 局部中间件
定义中间件
const mw = (res,res,next)={}
const mw2 = (res,res,next)={}
局部使用中间件
app.get('/',[mw,mw2],(req,res)=>{})
//或者
app.get('/',mw,mw2,(req,res)=>{})
中间件要在路由之前定义
路由级别中间件
router.use(中间件函数)
错误级别中间件
app.use((err,req,res,next)=>{})
注册错误级别中间件
错误级别中间件必须注册在路由之后,他会在抛出错误之后立即执行
express内置中间件
express.json()
解析请求体的json
中间件函数
app.use(express.json())
app.get('/json',(request,response)=>{
console.log(request.body)
response.send('ok')
})
express.urlencoded()
解析请求体的urlencoded
中间件函数
第三方中间件
安装引用注册…
自定义中间件
- 自定义中间件中需要监听
request
的data
事件(每次传送数据触发)和end事件(数据传送结束触发)
function(req,res,next){
let str = ''
req.on('data',(chunk)=>{
str += chunk
})
req.on('end',()=>{
req.body=qs.parse(str)//见下方
})
next()
}
定义接口
- 创建服务器
- 创建路由模块
- 注册路由模块
querystring模块
//导入
const qs = require('querystring')
//将字符串转换成对象
qs.parse(str)
跨域
cors
中间件解决跨域- 安装导入使用
- 默认只支持9个响应头和get,post,HEAD三中响应方式
npm i cors
const cors = require('cors')
app.use(cors())
- 设置响应头解决跨域
response.setHeader('Access-Control-Allow-Origin','*')
.setHeader
*
改为固定url
表示这有这个路径可以跨域Origin
改为Headers
,*
改为'响应头1,响应头2'
表示还可以允许这些响应头Origin
改为Methods
,*
改为'POST,DELEDE,'
表示支持这两种响应方式
jsonp
解决跨域- 只支持
get
请求的跨域 <script src='url'></script>
- 服务器配置
jsonp
接口时必须写在app.use(cors())
前面,不然还是cors
接口
- 只支持
//客户端
<script src="http://127.0.0.1:8080/jsonp"></script>
//服务器
app.get('/jsonp',(request,response)=>{
response.send(`alert('我来自服务器')`)//字符串形式的js代码
})
body-parser中间件
- 用于将post请求体的数据解析
- 安装,导入
- 使用
const bodyParser = require('body-parser');
app.use(bodyParser.json());//解析json数据
app.use(bodyParser.urlencoded({ extended: false }));//解析url类型数据
现在express一般都内置了直接
app.use(express.urlencoded({ extended: true }))
app.use(express.json())
express-session认证
- 常用于不需要跨域
- 安装session中间件npm i express-session
- 导入中间件const session = require(‘express-session’)
- 使用中间件并配置app.use(session({}))
const express = require('express')
const session = require('express-session')
const cors = require('cors')
const bodyParser = require('body-parser');
const app = express()、
app.use(cors())
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(session({
secret: 'admin',//值自定
resave: false,//固定写法
saveUninitialized: true//固定写法
}))
app.post('/login', (req, res) => {
if(req.body.username !=='admin' || req.body.password !== '0000'){
return res.send({status:1,msg:'登录失败'})
}
req.session.user = req.body//把请求体数据保存起来
req.session.isLogin = true//登陆状态设置为真
res.send('登陆成功')
})
app.listen(8080, () => {
console.log('服务器启动')
})
get请求没有请求体,ajax发送数据send(),数据类型由请求头的content-type决定
JWT认证
- 常用于需要跨域
- 最流行
- 存储在localStorage或sessionStorage
- 由3部分组成
Header.Payload(用户加密信息).Signature
使用
- 安装两个包,jsonwebtoken和express-jwt
- jsonwebtoken用于加密用户信息成JWT字符串
- express-jwt用于解密JWT字符串成JSON对象
- 导入
- 定义secret密钥
- jsonwebtoken.sign({})生成JWT字符串
- {}中包含3个参数用户信息{},密钥’',有效时间{expiresIn: ‘30s’}
- 注册expressJwt中间件
- 配置app.use(expressJWT({secret:密匙,algorithms: [“HS256”]}).unless({path:[/正则/]}))
- secret与algorithms必要
- unless指定哪些路径不需要访问权限
- 这个中间件会给req添加一个user属性存储解析的用户信息
- 配置app.use(expressJWT({secret:密匙,algorithms: [“HS256”]}).unless({path:[/正则/]}))
expressJwt这个包用法已经变了,到官网差查
const express = require('express')
//导入jsonwebtoken
const jwt = require('jsonwebtoken')
//导入express-jwt
const expressJwt = require('express-jwt')
const app = express()
const bodyParser = require('body-parser');
//定义密钥
const secretKey = 'xuzhou'
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//定义post接口,把生成的token传给客户端
app.post('/enter', (req, res) => {
let tokenStr = jwt.sign({ username: req.body.username }, secretKey, { expiresIn: '300s' })
res.send({
status: 200,
msg: '登录成功',
token: tokenStr
})
})
//注册express-jwt中间件,客户端登录时,中间件把token解析成用户数据并存储到req.user中
app.use(expressJwt({ secret:secretKey ,algorithms: ["HS256"]}).unless({ path: [/\/api\//] }))
//定义登录接口,验证token解析后是否为用户,返回相应值
app.get('/enterToken', (req, res) => {
if (req.user.username === 'xz') {
res.send('你已经登录')
}else{
res.send('你的token不对')
}
})
app.listen(8080, () => {
console.log('服务器启动');
})
注意中间件注册顺序
添加请求头Authorization
请求头值Bearer+空格+token
才能把token传给服务器
bcryptjs加密包
- 安装,导入
-bcrypt.hashSync(需要加密的字符串, salt)
;salt
表示盐,百度
表单验证包
太多,看喜好百度用
注意
express不允许send两次
Mysql
安装
- 百度
图视化工具使用
- 百度
sql语句
- 百度有语句大全
- 常用
insert into users (name,password) values ('xz','520')
update users set password = '5201314' where id < 6
delete from users where id = 6
select * from users where id = 4 and name = 'ls'
select * from users order by id desc
降序select * from users order by id asc
升序select * from users order by id asc, name desc
select count(*) from users where name = 'xz'
符合条件总数select count(*) as total from users where name = 'xz'
起别名
js文件中操作数据库
- 安装模块npm i mysql
- 查询和增添信息
//导入mysql模块
const mysql = require('mysql')
const database = mysql.createPool({
host:'127.0.0.1',//数据库地址
user:'root',//登录数据库账号
password:'admin123',
database:'demo01'//指定操作哪个数据库
})
//第一种增加写法
const user = {name:'xxxx',password:'3270280820909130910'}
//?占位
const sqlStr = 'insert into users (name,password) values (?,?)'
//[]中的数据一一对应占位符
database.query(sqlStr,[user.name,user.password],(error,results)=>{
if(error){
console.log(error.message)
}else{
console.log(results.affectedRows);//results.affectedRows的值为1表示执行成功
}
})
//第二种增加写法
const user2 = {name:'wo',password:'3270280820909130910'}
//?占位
const sqlStr2 = 'insert into users set ?'
//{}
database.query(sqlStr2,user2,(error,results)=>{
if(error){
console.log(error.message)
}else{
console.log(results.affectedRows);//results.affectedRows的值为1表示执行成功
}
})
//查询
database.query('select * from users',(error,results)=>{
if(error){
console.log(error.message)
}else{
console.log(results);
}
})
- 更新和删除
//第一种更新
const user = { id: 7, name: 'music', password: '00000000' }
const sqlStr = 'update users set name = ?,password = ? where id = ?'
database.query(sqlStr, [user.name,user.password,user.id], (err, results) => {
results.affectedRows === 1 ? console.log('更新成功') : console.log('错了');
})
//第二种更新
const user = { id: 7, name: 'music', password: '00049894944' }
const sqlStr = 'update users set ? where id = ?'
database.query(sqlStr, [user,user.id], (err, results) => {
results.affectedRows === 1 ? console.log('更新成功') : console.log('错了');
})
//删除
const sqlStr = 'delete from users where id = ?'
database.query(sqlStr,12,()=>{})