一、文件系统模块
1、读取文件内容
fs.readFile(读取文件路径,编码格式(可选),callback)
//err错误信息 dataStr获取到的数据
fs.readFile('./test/2.txt', 'utf8', (err, dataStr) => {
if (err) {
return console.log('读取失败' + err);
}
console.log(dataStr);
})
2、写入文件
fs.writeFile(写入文件路径,写入数据,编码格式(可选),callback)
fs.writeFile('./test/2.txt','test2222','utf8',(err)=>{
console.log(err); // 成功结果为null,失败显示错误信息
})
3、成绩案例
将 小红=99,小白=100,小黄=70,小黑=66,小绿=88
写成
小红:99
小白:100
小黄:70
小黑:66
小绿:88
const fs=require("fs")
fs.readFile('./test/成绩.txt','utf8',(err,dataStr)=>{
if(err) return console.log('读取文件失败'+err);
//把一个字符串分割成字符串数组
const arr=dataStr.split(',')
let newArr=[]
// console.log(arr);
arr.forEach((item,i)=>{
// console.log(item,i);
newArr.push(item.replace('=',':'))
})
// console.log(newArr);
// 将数组作为字符串返回
const newStr=newArr.join('\r\n')
console.log(newStr);
// 写入文件
fs.writeFile('./成绩-ok.txt',newStr,'utf8',(err)=>{
if(err){
return console.log('写入文件错误'+err.message);
}
console.log('文件写入成功');
})
})
4、路径拼接
__dirname为node运行的文件的所在路径
//拼接绝对路径
fs.readFile(__dirname + '/成绩-ok.txt', 'utf8', (err, dataStr) => {
console.log(err);
console.log(dataStr);
})
二、path路径模块
1、 path.join() 拼接路径
fs.readFile(path.join(__dirname,'成绩-ok.txt'),'utf8',(err,str)=>{
})
2、path.basename() 提取文件名字
console.log(path.basename('成绩-ok.txt','.txt')); //成绩-ok
3、path.extname() 提取后缀名
console.log(path.extname('成绩-ok.txt')); //.txt
三、HTTP模块
1、创建基本的web服务器
var http=require('http')
//创建web服务器
const server=http.createServer()
//监听请求事件
server.on('request',(req,res)=>{
console.log('有客户端请求我们的服务器');
// console.log(req);
// console.log(res);
})
//调用server.listen方法,即可启动web服务器
server.listen(8080,()=>{
console.log('http server running at http://127.0.0.1:8080');
})
2、req请求对象,res响应对象
server.on('request', (req, res) => {
// console.log(req);
//客户端请求的url地址
const url = req.url
//客户端的请求类型
const method = req.method
let content = `<h1>404 Not found!</h1>`
//设置 Content-Type 响应头,解决中文乱码的问题
res.setHeader('Content-Type', 'text/html; charset=utf-8')
//根据不同的url响应不同的html内容
if (url === '/' || url === '/index') {
content = `<h1>首页</h1>`
} else if (url === '/about') {
content = `<h1>关于页面</h1>`
}
const str = `请求地址是${url},请求方式是${method}`
console.log(str);
res.end(content) //将内容发送到客户端
})
3、自定义模块
(1)引入自定义模块
const m=require('./自定义模块')
console.log(m);
//获取指定属性
const {name,age}=require('./自定义模块')
console.log(name,age);
(2)创建自定义模块
1、 module.exports和exports暴露属性,结果以module.exports对象内的数据为准
2、在定义module.exports对象后,再用exports添加属性无效
结果为module.exports对象内的数据
module.exports={
name:'zs',
age:21,
say(){
console.log('everything will be ok');
}
}
//在定义module.exports后,再用exports添加属性无效
exports.age=88
exports.sex='man'
3、结果为{ id: 1, name: 'zs', age: 111, say: [Function (anonymous)] }
exports.id=1
module.exports.name='zs'
module.exports.age=18
exports.age=111
module.exports.say=()=>{
console.log('okk');
}
四、express
1、express创建最基本的服务器
const express = require('express')
const app = express()
app.listen(8080, () => {
console.log('express server running at http://127.0.0.1:8080');
})
app.get('/user', (req, res) => {
res.send({
name: 'zs',
age: 19
})
})
app.post('/user', (req, res) => {
res.send('请求成功')
})
//express获取参数
app.get('/', (req, res) => {
// 通过 req.query 可以获取到客户端发送过来的 查询参数
// 注意:默认情况下,req.query 是一个空对象
console.log(req.query)
res.send(req.query)
})
// 注意:这里的 :id 是一个动态的参数
//http://127.0.0.1:8080/user/3/xc
app.get('/user/:ids/:username', (req, res) => {
// req.params 是动态匹配到的 URL 参数,默认也是一个空对象
console.log(req.params)
res.send(req.params)
})
2、使用express.static对外提供静态资源
app.use(url前缀,express.static(文件路径))
// app.use(express.static('./clock'))
app.use('/clock',express.static('./clock'))
3、express路由
var express=require('express')
var router=express.Router() //创建路由对象
//挂载获取用户列表的路由
router.get('/user/list',(req,res)=>{
res.send('Get userlist')
})
router.post('/user/add',(req,res)=>{
res.send('Add new user')
})
module.exports=router //向外导出路由对象
4、中间件
(1)中间件的创建和使用
const express=require('express')
const app=new express()
//中间件函数
// const mw=function(req,res,next){
// console.log('这是最简单的中间件函数');
// next()
// }
// //将mw注册成全局生效的中间件
// app.use(mw)
app.use((req,res,next)=>{
console.log('这是最简单的中间件函数');
const time=Date.now()
// 为req对象挂载自定义属性,把属性共享给后面的路由
req.startTime=time
next()
})
app.get('/',(req,res)=>{
console.log('调用了/这个路由');
res.send('Home page'+req.startTime)
})
app.get('/user',(req,res)=>{
console.log('调用了/user这个路由');
res.send('User page'+req.startTime)
})
app.listen(8080,()=>{
console.log(('http://127.0.0.1'));
})
(2)错误级中间件
app.use((err,req,res,next)=>{
console.log(err);
res.send('404,可选择其他方式访问')
})
(3)express——post请求
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({extended:false}))
app.post('/user',(req,res)=>{
console.log(req.body);
res.send(req.body)
})
app.post('/book',(req,res)=>{
console.log(req.body);
res.send(req.body)
})
app.listen(8080, () => {
console.log('express server running at http://127.0.0.1:8080');
})
(4)body-parser
express内置的express.unlencoded中间件,就是基于body-parser进一步封装出来的
const parser=require('body-parser')
app.use(parser.urlencoded({extended:false}))
(5)自定义解析表单数据的中间件
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// 导入 Node.js 内置的 querystring 模块
const qs = require('querystring')
// 这是解析表单数据的中间件
app.use((req, res, next) => {
// 定义中间件具体的业务逻辑
// 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
let str = ''
// 2. 监听 req 的 data 事件
req.on('data', (chunk) => {
str += chunk
})
// 3. 监听 req 的 end 事件
req.on('end', () => {
// 在 str 中存放的是完整的请求体数据
// console.log(str)
// TODO: 把字符串格式的请求体数据,解析成对象格式
const body = qs.parse(str)
req.body = body
next()
})
})
app.post('/user', (req, res) => {
res.send(req.body)
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(8080, function () {
console.log('Express server running at http://127.0.0.1')
})
(6)express写接口
app.js
const express = require("express")
const app = express()
// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))
// 必须在配置 cors 中间件之前,配置 JSONP 的接口
//jsonp只支持get请求
app.get('/api/jsonp', (req, res) => {
const funName = req.query.callback
const data = {
name: 'zs',
age: 12
}
// 拼接一个函数的调用 callback(data)
const scriptStr = `${funName}(${JSON.stringify(data)})`
res.send(scriptStr)
})
//实现跨域
const cors = require("cors")
app.use(cors())
//导入路由
const routerAPI = require("./routerAPI")
app.use('/api', routerAPI)
app.listen(8080, () => {
console.log("sever opened");
})
routerAPI.js
const express=require("express")
const routerAPI=express.Router()
routerAPI.get('/get',(req,res)=>{
const query=req.query
res.send({
status:0,
msg:'GET请求成功',
data:query
})
})
routerAPI.post('/post',(req,res)=>{
const body=req.body
res.send({
status:0,
msg:'POST请求成功!',
data:body
})
})
routerAPI.delete('/delete',(req,res)=>{
res.send({
status:0,
msg:'delete请求成功!'
})
})
module.exports=routerAPI
测试接口跨域
<body>
<button id="btnGET">GET</button>
<button id="btnPOST">POST</button>
<button id="btnDelete">DELETE</button>
<button id="btnJSONP">JSONP</button>
<script>
//调用接口
$(function () {
// 1. 测试GET接口
$('#btnGET').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1:8080/api/get',
data: { name: 'zs', age: 20 },
success: function (res) {
console.log(res)
},
})
})
// 2. 测试POST接口
$('#btnPOST').on('click', function () {
$.ajax({
type: 'POST',
url: 'http://127.0.0.1:8080/api/post',
data: { bookname: '水浒传', author: '施耐庵' },
success: function (res) {
console.log(res)
},
})
})
// 3. 为删除按钮绑定点击事件处理函数
$('#btnDelete').on('click', function () {
$.ajax({
type: 'DELETE',
url: 'http://127.0.0.1:8080/api/delete',
success: function (res) {
console.log(res)
},
})
})
// 4. 为 JSONP 按钮绑定点击事件处理函数
$('#btnJSONP').on('click', function () {
$.ajax({
type: 'GET',
url: 'http://127.0.0.1:8080/api/jsonp',
dataType: 'jsonp',
success: function (res) {
console.log(res)
},
})
})
})
</script>
</body>
五、MySQL
1、sql语句
SELECT * FROM test01.users;
-- 插入数据
insert into users(username,password) values ('孙悟空','111111');
-- 修改数据
update users set password='999999' where id=3;
-- 删除数据
delete from users where id=6;
-- 查询指定id的数据
select username from users where id=1;
-- 查询指定id和状态的数据
select * from users where id<3 and status=0;
-- 查询满足指定id或状态的数据
select * from users where id<3 or status=1;
-- 查询用户表的用户名和密码,默认升序,asc结果升序,desc结果降序
select username,password from users order by id asc;
select username,password from users order by id desc;
-- 查询用户数量
select count(id) from users;
-- 查询用户数量,并设置数量名
select count(id) as total from users where status=0;
-- 修改id为2的用户名为寻常
update users set username='寻常' where id=2;
2、mysql模块
(1)配置和测试mysql模块
const mysql = require('mysql')
//建立与MySQL数据库的连接
const db = mysql.createPool({
host: '127.0.0.1',
port: 3306,
user: 'root',
password: '123456',
database: 'test01'
})
db.query('select 1', (err, results) => {
if (err) return console.log(err.message)
console.log(results); //结果为[ RowDataPacket { '1': 1 } ],mysql模块运行正常
})
(2)查询
//查询user表 用select查询,执行的结果是数组
const sqlStr='select * from users'
db.query(sqlStr,(err,results)=>{
if(err)return console.log(err.message)
console.log(results);
})
(3)插入数据
//插入数据
const user = {
username: '初雪',
password: '909090'
}
const sqlStr = `insert into users(username,password) values (?,?)`
db.query(sqlStr,[user.username,user.password], (err, results) => {
if (err) {
return console.log(err.message);
}
if (results.affectedRows === 1) {
console.log('插入数据成功');
}
})
// 简易插入数据
const user={
username:'阿米娅',
password:'898989'
}
const sqlStr=`insert into users set ?`
db.query(sqlStr,user,(err,results)=>{
if(err){
return console.log(err.message);
}
if(results.affectedRows === 1){
console.log('插入数据成功');
}
})
(4)更新数据
//更新数据
const user ={
id:3,
username:'哪吒',
password:'111111'
}
const sqlStr='update users set username=?,password=? where id=?'
db.query(sqlStr, [user.username,user.password,user.id], (err, results) => {
if (err) return console.log(err.message)
if (results.affectedRows === 1) {
console.log('更新数据成功');
}
})
//简易更新数据
const user ={
id:3,
username:'河图',
password:'898989'
}
const sqlStr=`update users set ? where id=?`
db.query(sqlStr,[user,user.id],(err,results)=>{
if(err){
return console.log(err.message);
}
if(results.affectedRows === 1){
console.log('更新数据成功');
}
})
(5)删除数据(可修改用户状态假性删除用户更安全)
//删除数据
const sqlStr='delete from users where id=?;'
db.query(sqlStr, 12, (err, results) => {
if (err) return console.log(err.message)
if (results.affectedRows === 1) {
console.log('删除数据成功');
}
})
//可通过修改status假性删除数据
//标记删除
const sqlStr='update users set status=1 where id=?'
db.query(sqlStr, 22, (err, results) => {
if (err) return console.log(err.message)
if (results.affectedRows === 1) {
console.log('删除数据成功');
}
})
六、身份认证
1、session
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// TODO_01:请配置 Session 中间件
const session = require('express-session');
app.use(
session({
secret: 'itheima',
resave: false,
saveUninitialized: true
})
)
// 托管静态页面
app.use(express.static('./pages'))
// 解析 POST 提交过来的表单数据
app.use(express.urlencoded({ extended: false }))
// 登录的 API 接口
app.post('/api/login', (req, res) => {
// 判断用户提交的登录信息是否正确
if (req.body.username !== 'admin' || req.body.password !== '000000') {
return res.send({ status: 1, msg: '登录失败' })
}
// TODO_02:请将登录成功后的用户信息,保存到 Session 中
// 只有成功配置了express-session,才能通过req.session来访问和使用session对象
req.session.user = req.body //用户的信息
req.session.islogin = true //用户的登陆状态
res.send({ status: 0, msg: '登录成功' })
})
// 获取用户姓名的接口
app.get('/api/username', (req, res) => {
// TODO_03:请从 Session 中获取用户的名称,响应给客户端
if(!req.session.islogin){
return res.send({
status:1,
msg:'fail'
})
}
res.send({
status:0,
msg:'success',
username:req.session.user.username
})
})
// 退出登录的接口
app.post('/api/logout', (req, res) => {
// TODO_04:清空 Session 信息
req.session.destroy()
res.send({
status:0,
msg:'退出登录成功'
})
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(8080, function () {
console.log('Express server running at http://127.0.0.1:8080')
})
2、jwt
// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()
// TODO_01:安装并导入 JWT 相关的两个包,分别是 jsonwebtoken 和 express-jwt
const jbt = require('jsonwebtoken')
const express_jwt = require('express-jwt')
// 允许跨域资源共享
const cors = require('cors')
app.use(cors())
// 解析 post 表单数据的中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
// TODO_02:定义 secret 密钥,建议将密钥命名为 secretKey
const secretKey = 'itheima No1 ^_^'
// TODO_04:注册将 JWT 字符串解析还原成 JSON 对象的中间件,指定哪些接口不需要访问权限
app.use(
express_jwt({
secret: secretKey,
algorithms: ['HS256']
}).unless({
path: [/^\/api\//]
})
)
// 登录接口
app.post('/api/login', function (req, res) {
// 将 req.body 请求体中的数据,转存为 userinfo 常量
const userinfo = req.body
// 登录失败
if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
return res.send({
status: 400,
message: '登录失败!'
})
}
// 登录成功
// TODO_03:在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
const tokenStr = jwt.sign(
{ username: userinfo.username }, //用户的信息对象
secretKey, //加密的密钥
{ expiresIn: '30s' } //配置对象
)
res.send({
status: 200,
message: '登录成功!',
token: tokenStr // 要发送给客户端的 token 字符串
})
})
// 这是一个有权限的 API 接口
app.get('/admin/getinfo', function (req, res) {
// TODO_05:使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端
console.log(req.user);
res.send({
status: 200,
message: '获取用户信息成功!',
data: req.user // 要发送给客户端的用户信息
})
})
// TODO_06:使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
if (err.name === 'UnauthorizedError') {
return res.send({
status: 401,
message: '无效的token'
})
}
res.send({
status: 500,
message: '未知的错误'
})
})
// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(8080, function () {
console.log('Express server running at http://127.0.0.1:8080')
})