当前位置:网站首页 > 后端开发 > 正文

node做后端

node的语法基础

JavaScript语法
变量
注释
数据类型
函数
闭包
控制台console
console.log()

在REPL环境中输入console

>console

console.log()标准输出流的输出,console.log('node.js is powerful')

console.warn(),console.error(),console.info()
console.warn('%s%s','node.js','is','powerful'); //node.jsis powerful console.warn('%s%s%s','node.js','is','powerful'); //node.jsispowerful console.info('%d','node.js') //NaN console.log('%d','node.js','is','powerful'); //NaN is powerful console.error('%d','node.js'); //NaN console.error('%d','node.js','is','powerful'); //NaN is powerful 
console.dir()

用于将一个对象的信息输出到控制台。

const obj={ 
    name:'node.js', get:function(){ 
    console.log('get'); } set:function(){ 
    console.log('set'); } } console.log(obj); 
console.time(),console.timeEnd()

用于统计一段代码的运行的时间。

console.time('total time'); console.time('time1'); for(var i=0;i<10000;i++){ 
    } console.timeEnd('time1'); console.time('time2'); for(var i=0;i<10000;i++){ 
    } console.timeEnd('time2'); console.timeEnd('total time'); 
console.trace()

用于输出当前位置的栈的信息。

node中的包管理

NPM介绍
NPM常用命令

npm -v,npm version;

npm init可以生成package.json文件;

npm install;

package.json文件

package.json文件是一个提供包描述的文件。

模块加载原理与加载方式
require加载模块

对于原生模块:

const http=require('http'); http.createServer( //your code ) 

对于文件模块:

const myModule=require('./node/myModule')

exports导出模块
node核心模块
http模块——创建HTTP服务器,客户端

node.js服务器端:

const http=require('http'); const server=http.createServer(function(req,res){ 
    //基于事件的http服务器 res.writeHead(200,{ 
    'content-type':'text/plain'}); res.end('Hello node.js'); }); server.listen(3000,function{ 
    console.log('listening port 3000'); }); 
const http=require('http'); const server=new http.Server(); server.on('request',function(req,res){ 
    //基于事件的http服务器 res.writeHead(200,{ 
    'content-type':'text/plain'}); res.end('Hello node.js'); }); server.listen(3000,function{ 
    console.log('listening port 3000'); }); 

客户端向http服务器发送请求:

http.request(option[,callback]);

http.get(option[,callback]);

const http=require('http'); let reqData=''; http.request({ 
    'host':'127.0.0.1', 'port':'3000', 'method':'get' },function(res){ 
    res.on('data',function(chunk){ 
    reqData+=chunk; }) res.on('end',function(){ 
    console.log(reqData); }); }); 
const http=require('http'); let reqData=''; let option={ 
    'host':'127.0.0.1', 'port':'3000' }; const req=http.request(option); req.on('response',function(res){ 
    res.on('data',function(chunk){ 
    reqData+=chunk; }); res.on('end',function(){ 
    console.log(reqData); }); }); 
url模块——url地址处理

使用url模块

const url=require('url'); let parseUrl='https://www.google.com/?q=node.js'; let urlObj=url.parse(parseUrl); console.log(urlObj) 

使用url.format()

const url=require('url'); let urlObj={ 
    'host':'www.google.com', 'port':'3000', 'protocol':'https', 'search':'?q=node.js' }; let urladdress=url.format(urlObj); console.log(urladdress); 
querystring模块——查询字符串处理

querystring.parse():将查询字符串反序列化为一个对象,类似JSON.parse();

querystring.stringify():将一个对象序列化为一个字符串,类似JSON.stringify();

const querystring=require('querystring'); let obj={ keyWord:'node.js', name:'huruji' }; let str=querystring.stringify(obj); console.log(str); 
node常用模块
util模块——实用工具

util.inspect():返回一个对象反序列化形成的字符串;

util.format():返回一个使用占位符格式化的字符串;

util.log():控制台输出,类似console.log();

const util=require('util'); let obj={ 
    keyWord:'node.js', name:'huruji' }; let str=util.inspect(obj); console.log(str); 
path模块——路径处理

path模块提供一系列处理文件路径的工具:

path.join():将所有的参数连接起来,返回一个路径;

path.extaname():返回路径的扩展名;

path.parse():将路径解析成一个路径对象;

path.format():接收路径对象为参数,返回一个完整的路径地址。

const path=require('path'); let outputPath=path.join(_dirname,'node','node.js') console.log(outputPath) 
const path=require('path'); const str='C:/frontEnd/node/node.js'; let obj=path.parse(str); console.log(obj); 
dns模块

dns模块是域名处理和解析:

dns.resolve():将一个域名解析成一个数组;

dns.lookup():返回第一个被发现的IPv4或IPv6地址;

dns.reverse():通过IP解析域名。

const dns=require('dns'); let domain='baidu.com'; dns.resolve(domain,function(err,address){ 
    if(err){ 
    console.log(err); return; } console.log(address); }) 

文件系统

node文件系统介绍
同步与异步
const fs=require('fs'); //异步操作读取文件 fs.unlink('./temp/hello',(err)=>{ 
    if(err) throw err; console.log('successfully') }) 
fs模块中的类和文件的基本信息
文件路径
基本文件操作
打开文件

fs.open(path,flags[,mode],callback)

path:文件的路径;

flags:文件打开方式;

mode:设置文件模式;

callback:回调函数,同时带有二个参数。

flag值 说明
r 打开文件以读取文件并在文件不存在时引发异常。
r+ 打开文件进行读写。如果文件不存在,则引发异常。
rs+ 以同步模式打开文件以进行读写。
w 打开文件进行写入。如果文件不存在,则会创建该文件。
wx 与“ w”相同,但如果存在路径则失败
w+ 打开文件进行读写。如果文件不存在,则会创建该文件。
wx+ 与“ w +”相同,但如果存在路径则失败。
a 打开要追加的文件。如果文件不存在,则会创建该文件。
var fs=require('fs'); fs.open('text.txt','r+',function(err,fd){ 
    if(err){ 
    return console.log(err) }; }); 
关闭文件

fs.close(fd,callback)

读取文件

fs.read(fd,buffer,offset,length,position,callback)

写入文件

fs.appendFile(file,data[,options],callback)

node网络开发

构建TCP服务器
构建TCP客户端
构建HTTP服务器
利用UDP协议传输数据与发送信息

node数据库开发

express-监听GET和POST请求

req.query
const express = require('express'); const app = express(); app.get('/get', function(req, res) { 
    // 直接返回对象 console.log(req.query); res.send(req.query) }); app.listen('7777', () => { 
    console.log('7777'); }); 

在这里插入图片描述

req.params
const express = require('express'); const app = express(); app.get('/get/:id', function(req, res) { 
    // 直接返回对象 console.log(req.params); // res.json()返回json数据(自动处理)并结束响应 res.send(req.params) // res.send({ name: 'abc' }); }); app.listen('7777', () => { 
    console.log('7777'); }); 

在这里插入图片描述

托管静态资源

托管多个静态资源目录,多次调用express.static()

const express=require('express') const app=express() app.use(express.static('./public')) app.listen(7777,()=>{ 
    console.log('7777') }) 

在这里插入图片描述

挂载路径前缀
app.use('/public',express.static('./public')) 

在这里插入图片描述

express路由

在express中,路由指的是客户端的请求与服务器处理函数之间的映射关系。

请求类型,请求的url地址,处理函数;

const express=require('express') const app=express() app.get('/user',(req,res)=>{ 
    res.send('hello world') }) app.post('/user',(req,res)=>{ 
    res.send('post') }) app.listen(7777,()=>{ 
    console.log('7777') }) 
模块化路由

1.创建路由模块对应的js文件;

2.调用express.Router()函数创建路由对象;

3.向路由实例对象上挂载具体的路由;

4.使用module.exports向外共享路由对象;

5.使用app.use()函数注册路由模块;

const express=express() const router=express.Router() router.get('/user/list',(req,res)=>{ 
    res.send('get user list') }) router.post('/user/add',(req,res)=>{ 
    res.send('add new user') }) module.exports=router 
const express=require('express') const app=express() app.listen(7777,()=>{ 
    console.log('http://127.0.0.1') }) 
为路由模块添加前缀

类似托管静态资源

const express=require('express') const app=express() //导入路由模块 const router=require('./router') //注册路由模块 app.use('api',router) app.listen(7778,()=>{ 
    console.log('http://127.0.0.1') }) 
中间件

本质上是一个function处理函数;

多个中间件之间,共享同一份req和res。

app.get('/',(req,res,next){ 
    next() }) 

next()是实现多个中间件连续调用,表示把流转关系转交给下一个中间件或者路由;

定义在中间件函数
const express=require('express') const app=express() const mm=function(req,res,next){ 
    console.log('这是一个最简单的中间件函数') //把流转关系,转交给下一个中间件或者路由 next() } app.listen(7777,()=>{ 
    console.log('7777') }) 
全局生效的中间件
const express=require('express') const app=express() const mm=function(req,res,next){ 
    console.log('这是一个最简单的中间件函数') //把流转关系,转交给下一个中间件或者路由 next() } app.use(mm) app.listen(7777,()=>{ 
    console.log('7777') }) 
定义全局生效中间件的简化形式
const express=require('express') const app=express() app.use((req,res,next)=>{ 
    console.log('这是最简单的中间函数') next() }) app.get('/user',(req,res)=>{ 
    res.send('Home page') }) app.listen(7778,()=>{ 
    console.log('7778') }) 
局部生效的中间件

不使用app.use()定义的中间件,叫做局部生效的中间件。

const mv1=function(req,res,next){ 
    console.log('这是中间件函数') next() } app.get('/',mv1,function(req,res)=>{ 
    res.send('Home Page') }) 
定义多个中间件
app.get('/',mv1,mv2,(req,res)=>{ 
   res.send('Home Page')}) app.get('/',[mv1,mv2],(req,res)=>{ 
   res.send('layout page')}) 

在这里插入图片描述

中间件的分类

应用级别的中间件

app.use() app.get() app.post() 

路由级别的中间件

绑定express.Router()

错误级别的中间件

专门来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。

错误级别的中间件,必须注册在所有的路由之后;

const express=require('express') const app=express() app.get('/',(req,res)=>{ 
    throw new Error('服务器内部发生错误') res.send('Home Page') }) app.use((err,req,res,next)=>{ 
    console.log(err.message) res.send('Error'+err.message) }) app.listen(7778,()=>{ 
    console.log('7778') }) 

express内置的中间件

express.static() 托管静态资源 express.json() 解析json格式的请求体数据 express.urlencoded() app.use(express.json()) 
//raw-json数据 const express=require('express') const app=express() //除了错误级别的中间件,其他的中间件,必须在路由之前进行配置 app.use(express.json()) app.post('/user',(req,res)=>{ 
    //在服务器,可以使用req.body这个属性,来接收客户端发送过来的请求体数据 //默认情况下,如果不配置解析表单数据的中间件,则req.body默认=undefined console.log(req.body) res.send('ok') }) app.listen(7778,()=>{ 
    console.log('7778') }) 

在这里插入图片描述

在这里插入图片描述

第三方中间件

自定义中间件
app.use((req,res,next)=>{ 
    }) 

监听req的data事件

 app.use((req,res,next)=>{ 
    let str='' req.on('data',(chunk)=>{ 
    str+=chunk }) }) 

监听req的end事件

 app.use((req,res,next)=>{ 
    let str='' req.on('data',(chunk)=>{ 
    str+=chunk }) req.on('end',()=>{ 
    //str中存放的是完整的请求体数据 console.log(str) }) }) app.use('/user',(req,res)=>{ 
    res.send('ok') }) 

querystring模块解析请求体数据

解析出来的数据对象挂载为req.body

req.on('end',()=>{ 
    const body=qs.parse(str) req.body=body next() }) 

将自定义中间件封装为模块

const qs=require('querystring') const bodyParser=(req,res,next)=>{ 
    let str='' req.on('data',(chunk)=>{ 
    str+=chunk }) req.on('end',()=>{ 
    const body=qs.parse(str) req.body=body next() }) } module.exports=bodyParser 
const express=require('express') const app=express() //导入封装的中间件模块 const custom=require('./body-parser') app.use(custom) app.post('/user',(req,res)=>{ 
    const body=qs.parse(str) res.send('ok') }) app.listen(7778,()=>{ 
    console.log('7778') }) 
使用express写接口
编写get接口
const express=require('express') const router=express.Router() router.get('/get',(req,res)=>{ 
    //req.query获取客户端通过查询字符串,发送到服务器的数据 const query=req.query //res.send()方法,向客户端响应处理的结果 res.send({ 
    status:0, msg:'GET请求成功', data:query }) }) module.exports=router 
const express=require('express') const app=express() const router=require('./router') app.use('/api',router) app.listen(7777,()=>{ 
    console.log('express server running at http://127.0.0.1') }) 

在这里插入图片描述

编写post接口
const express=require('express') const router=express.Router() router.get('/get',(req,res)=>{ 
    //req.query获取客户端通过查询字符串,发送到服务器的数据 const query=req.query //res.send()方法,向客户端响应处理的结果 res.send({ 
    status:0, msg:'GET请求成功', data:query }) }) router.post('/post',(req,res)=>{ 
    //通过req.body获取请求体中包含的url-encoded格式的数据 const body=req.body res.send({ 
    status:0, msg:'POST请求成功', data:body }) }) module.exports=router 
const express=require('express') const app=express() //配置解析表单数据的中间件 app.use(express.urlencoded({ 
   extended:false})) const router=require('./router') app.use('/api',router) app.listen(7777,()=>{ 
    console.log('express server running at http://127.0.0.1') }) 

在这里插入图片描述

CORS跨域资源共享

解决接口跨域问题的方案主要有二种:

CORS(主流的解决方案)

JSONP(有缺陷的解决方案:只支持GET请求)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

jsonp接口

浏览器通过

//优先创建jsonp接口 app.get('/api/jsonp',(req,res)=>{ 
   }) app.use(cors) 
const express=require('express') const app=express() //配置解析表单数据的中间件 app.use(express.urlencoded({ 
   extended:false})) app.get('/api/jsonp',(req,res)=>{ 
    //定义接口的具体实现过程 const funName=req.query.callback //要发送到客户端的数据对象 const data={ 
   name:'zs',age:22} //拼接出一个函数的调用 const scriptStr=`${ 
     funName}(${ 
     JSON.stringify(data)})` res.send(scriptStr) }) const cors=require('cors') app.use(cors) const router=require('./router') app.use('/api',router) app.listen(7777,()=>{ 
    console.log('express server running at http://127.0.0.1') }) 

在这里插入图片描述

前后端身份认证

服务端渲染使用session认证

前后端分离使用JWT认证

Session认证机制
cookie

存储在用户浏览器中不超过4KB的字符串。由一个名称,一个值和其他;

特征:

1.自动发送;

2.域名独立;

3.过期时限;

4.4KB限制;

在这里插入图片描述

在这里插入图片描述

配置使用session中间件
npm install express-session const session=require('express-session') app.use( session({ 
    secret:'keyboard cat', resave:false, saveUninitialized:true }) ) 
向session中存数据
app.post('/',(req,res)=>{ 
    if(req.body.username!=='admin'||req.body.password!=='000000'){ 
    return res.send({ 
   status:1,msg:'登陆失败'}) } //成功配置express-session这个中间件之后,才能通过req点出来这个session属性 req.session.user=req.body //用户的信息 req.session.islogin=true //用户的登陆状态 }) 
从session中取数据
app.get('/',(req.res)=>{ 
    //判断用户是否登录 if(!req.session.islogin){ 
    return res.send({ 
   status:1,msg:'fail'}) } res.send({ 
    status:0, mgs:'success', username:req.session.user.username }) }) 

清空session

app.post('/',(req,res)=>{ 
    req.session.destroy() res.send({ 
    status:0, msg:'退出登录成功' }) }) 
JWT认证机制

在这里插入图片描述

JWT的组成部分

header,payload(有效载荷),signature(签名)

Header.Payload.Signature 
导入jwt相关的包
//导入用于生成jwt字符串的包 const jwt=require('jsonwebtoken') //用于将客户端发送过来的jwt字符串,解析还原成json对象的包 const expressJWT=require('express-jwt') 
定义secret密钥

为了保证jwt字符串的安全性,防止jwt字符串在网络传输过程中被别人激活成功教程,需要定义一个用于加密和解密的secret密钥:

const secretKey='ithema No1' 
登录成功后生成jwt字符串

调用jsonwebtoken包提供的sign()方法,将用户信息加密成jwt字符串,响应给服务器:

app.post('/api/login',(req,res)=>{ 
    res.send({ 
    status:200, messsage:'登录成功', //调用jwt.sign()生成jwt字符串,三个参数分别是:用户信息对象,加密密钥,配置对象 token:jwt.sign({ 
   username:userinfo.username},secretKey,{ 
   expiresIn:'30s'}) }) }) 
将jwt字符串还原为json对象

客户端每次在访问哪些有权限接口时,都需要主动通过请求头中的Authorization字段,将token字符串发送到服务器进行身份认证。

服务器通过express.jwt中间件,自动将客户端发送过来的token解析成json对象;

app.use(expressjwt({ 
   secret:secretKey}).unless({ 
   path:[/^\/api\//]})) 
使用req.user获取用户信息

项目

根据id获取文章分类数据
exports.get_cate={ 
    params:{ 
    id } } router.get('/cates/:id',expressJoi(get_cate),artcate_handler.getArtcateById) exports.getArtcateById=(req,res)=>{ 
    const sql=`select * from ev_article where id=?` db.query(sql,req.params.id,(err,results)=>{ 
    if(err) return res.cc(err) if(results.length!==1) return res.cc('获取文章分类数据失败!') res.send({ 
    status:0, message:'获取文章分类数据成功!', data:results[0] }) }) res.send('ok') } 
postman

在这里插入图片描述

前端
export const deleteRoom=(roomid)=>{ 
    return http({ 
    url:`/location/delete/${ 
     roomid}`, method:'GET', }) } const handleDelete =async (row) => { 
    const res=await deleteRoom(row.roomid) if(res.data.status===0){ 
    ElMessage({ 
    type: 'success', message:res.data.message }) getAll() }else{ 
    ElMessage.error(res.data.message) } console.log(res.data) }; 
根据id获取数据
const db=require('../db/index') exports.getArtcate=(req,res)=>{ 
    //未删除为0,删除为1 const sql=`select * from ev_article_cate where is_delete=0 order by id asc` db.query(sql,(err,results)=>{ 
    if(err) return res.cc(err) res.send({ 
    status:0, message:'获取文章分类数据成功', data:results }) }) res.send('ok') } 
前端
 export const getAllAPI=()=>{ 
    return http({ 
    url:'/location/all', method:'GET' }) } 
根据id新增数据
exports.postArtcate=(req,res)=>{ 
    //定义查询的name与alias是否被占用的sql语句 const sql=`select * from ev_article_cate where name=? or alias=?` db.query(sql,[req.body.name,req.body.alias],(err,results)=>{ 
    if(err) return res.cc(err) if(results.length===2) return res.cc('name,alias被占用') if(results.length===1 && results[0].name===req.body.name&&results[0].alias===req.body.alias) return res.cc('name,alias被占用') if(results.length===1&&results[0].name===req.body.name) return res.cc('name,alias被占用') if(results.length===1&&results[0].alias===req.body.alias) return res.cc('name,alias被占用') //TODO 都可用,执行添加 const sql=`insert into ev_artcile_cate set ?` db.query(sql,req.body,(err,results)=>{ 
    if(err) return res.cc(err) if(results.affectedRows!==1) return res.cc('新增文章分类失败!') res.cc('新增文章分类成功!',0) }) }) } 

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

postman

在这里插入图片描述

前端
 export const addUser = (formData) => { 
    const data = new URLSearchParams(formData); return http({ 
    url: '/location/adduser', method: 'POST', headers: { 
    'Content-Type': 'application/x-www-form-urlencoded', }, data: data.toString() }); } const form = ref({ 
    locationid: '', roomid:'', sum:'', is_delete:0 }) const adddialog=async()=>{ 
    dialogFormVisible.value=false const res=await addUser(form.value) console.log(res.data) if(res.data.status===0){ 
    ElMessage({ 
    type: 'success', message: '新增宿舍成功' }) getAll() }else{ 
    ElMessage.error('新增宿舍失败') } } 
根据id更新数据
//校验规则 exports.update_cate={ 
    body:{ 
    id, name, alias } } router.post('/updatecates',expressJoi(update_cate),artcate_handler.updateCateById) exports.updateCateById=(req,res)=>{ 
    //定义查重的sql语句 const sql=`select * from ev_article where Id<>? and (name=? or alias=?)` db.query(sql,[req.body.Id,req.body.name,req.body.alias],(err,results)=>{ 
    if(err) return res.cc(err) //判断name,alias if(results.length===2) res.cc('name,alias被占用') if(results.length===1&&results[0].name===req.body.name&&results[0].alias===req.body.alias) res.cc('name,alias被占用') if(results.length===1&&results[0].name===req.body.name) res.cc('name被占用') if(results.length===1&&results[0].alias===req.body.alias) res.cc('alias被占用') const sql=`update ev_article set ? where Id=?` db.query(sql,[req.body,req.body.Id],(err,results)=>{ 
    if(err) return res.cc(err) if(results.affectedRows!==1) return res.cc('更新失败') res.cc('更新文章分类成功',0) }) }) res.send('ok') } 
根据id删除数据
//验证规则对象----删除 const id=joi.number().integer().min(1).required() exports.delete_cate={ 
    params:{ 
    id } } router.get('/delete/:id',expressJoi(delete_cate),artcate_handler.deleteCateById) exports.deleteCateById=(req,res)=>{ 
    const sql=`update ev_article set is_delete=1 where id=? ` db.query(sql,req.params.id,(err,results)=>{ 
    if(err) return res.cc(err) if(results.affectedRows!==1) return res.cc('删除文章分类失败!') res.cc('删除文章分类成功!',0) }) res.send('ok') } 
到此这篇node做后端的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • vuejs后端开发2024-10-30 23:30:02
  • 后端简历项目2024-10-30 23:30:02
  • Go后端开发_后端开发需要学什么2024-10-30 23:30:02
  • 后端开发岗位要求汇总表2024-10-30 23:30:02
  • 后端开发的发展趋势是什么意思2024-10-30 23:30:02
  • 后端开发发展学习路线_后端开发发展方向2024-10-30 23:30:02
  • java后端开发需要掌握什么技能2024-10-30 23:30:02
  • 后端开发工程师岗位要求2024-10-30 23:30:02
  • java后端开发技术2024-10-30 23:30:02
  • 后端开发基础能力以及就Java的主流开发框架介绍2024-10-30 23:30:02
  • 全屏图片