二、node介绍node是一个运行js的环境。浏览器也是运行js的环境。两者的区别是浏览器会调用window和document。但是node没有node很多模块的api,比如文件系统访问功能node可以切换运行环境(切换版本?)node没有使用bable来转换node使用commonJS,需要使用require2-2的nodejs和js的区别nodejs=nodejsapi+ecmascriptHandlehttp,handlefiles等2-3commonjsmodule.export()require2-4,5debuger的inspectprotocol--inspect==9229chrome://inspect/#devices4.接口用于开发博客项目4-1http从url到浏览器的过程概述?首先解析dns,解析完成后发送请求,通过http协议建立tcp链接,然后传输文件。浏览器获取数据,然后构建dom树和css树。合并成渲染树,然后渲染注入js。DNS解析,建立TCP连接,发送http请求服务器收到http请求,处理并返回。客户端接收返回数据,处理数据,(如渲染页面,执行js)Remote地址为dns查询结果4-4处理http请求综合示例consthttp=require("http");constport=3000constserver=http.createServer((req,res)=>{res.setHeader("Content-Type","application/json")consturl=req.urlconstmethod=req.methodres.end(`${url}${method}`);})server.listen(port,()=>{console.log(`serverrunningathttp://localhost:${port}/`)})console.log("ok")4-5搭建开发环境使用nodemon检测文件变化并自动重启node。corss-env设置环境变量npminodemoncross-env--save-dev"scripts":{"test":"echo\"Error:notestspecified\"&&exit1","dev":"cross-envNODE_ENV=devnodemon./bin/www.js"},4-6初始化路由hostname:nodejs.cnpathname:/api/blog/listquery:?name=zhangsan&keyword=123constmethod=res.method//postgetconsturl=res.url//urlconstpath=res.url.split("?")[0]//4-7开发路由创建SuccessModel和ErrorModel。类BaseModel{constructor(data,message){if(typeofdata==="string"){this.message=data;消息=空;data=null}if(data){this.data=data;}if(message){this.message=message;}}}classSuccessModelextendsBaseModel{constructor(data,message){super(data,message);this.error=0}}classErrorModelextendsBaseModel{constructor(data,message){super(data,message);this.error=-1}}module.exports={SuccessModel,ErrorModel}4-8开发路径由(博客详情路径由)constfs=require('fs');constpath=require('path');functiongetFileContent(fileName){constfullFileName=path.resolve(__dirname,'file',fileName)constpromise=newPromise((resolve,reject)=>{fs.readFile(fullFileName,(err,data)=>{if(err){拒绝(错误);}解析(JSON.解析(数据));})})returnpromise;}getFileContent('a.json').then(aDate=>{console.log(aDate);returngetFileContent(aDate.next);}).then((bData)=>{console.log(bData);returngetFileContent(bData.next);}).then((cData)=>{console.log(cData);});4-9开发路由(ProcessingPOSTData)//用于处理postdataconstgetPostData=(req)=>{constpromise=newPromise(()=>{if(req.method!=='POST'){resolve({})return}if(req.headers['content-type']!=="application/json"){resolve({})return}})//监听流数据letpostData=''res.on('data',chunk=>{postData+=chunk.toString()})res.on('end',()=>{if(!postData){resolve({})return}resolve(JSON.parse(postData))})returnpromise}更新和删除数据,etc....5数据库MySqlusemyblog;--查表--显示tables;--insertintoblogs(title,content,createtime,author)values("市民胡女2的标题","市民胡女2的内容",1585645673144,"mjmjmj");SELECT*FROMmyblog.usersLIMIT0,1000;--selectusernamefromusers;--select*fromuserswherepasswordlike'%1%'orderbyiddesc;--select*fromblogs;--ALTERUSER'root'@'localhost'标识为mysql_native_passwordBY'password'PASSWORDEXPIRENEVER;--ALTERUSER'root'@'localhost'IDENTIFIEDWITHmysql_native_passwordBY'11111111';--flushprivileges--insertintoblogs(title,content,createtime,author)值('hhhhhh','jjhhhhh',1585646800912,'mjmjmj');--selectusername,realnamefromuserswhereusername='mjmjmj'andpassword='321654a'--更新--SETSQL_SAFE_UPDATES=0;--更新用户设置状态=0;--updateuserssetusername='huhuhu'whereid='2';--删除--deletefromblogswhereid='1';5.4nodejs操作数据库constmysql=require('mysql');constcon=mysql.createConnection({主机:'localhost',用户:'root',password:'11111111',port:'3306',database:'myblog',})//开始连接con.connect()//执行sqlconstsql='select*fromusers;';con.query(sql,(err,result)=>{if(err){console.log(err);return;}console.log(result);})con.end();constmysql=require('mysql');const{MYSQL_CONF}=require("../conf/db");//创建连接对象constcon=mysql.createConnection(MYSQL_CONF);//建立连接con.connect();//统一执行sql函数functionexec(sql){constpromise=newPromise((resolve,reject)=>{con.query(sql,(err,result)=>{if(err){reject(err);return}resolve(result)})})returnpromise;}con.end();module.exports={exec}6.2Cookie介绍什么是cookie?js是如何操作cookies的,如何在浏览器中查看cookies?服务器端操作cookies来实现登录验证。特点:最大5kb不跨域共享,可以保存结构化数据。每次发送http请求时,都会将请求域的cookie发送给cookie。服务器端可以修改cookie返回给客户端client。端也可以通过js修改cookie,返回给服务端(受限),看请求的是哪个域,请求的是哪个域,请求头中包含哪个cookiecookie的本地缓存cookiedomin:cookie生效的域名路径:是cookie的有效路径。修改cookie使用localStorage,本地修改cookie的情况不多nodejs修改cookie//解析cookiereq.cookie={}constcookieStr=req.headers.饼干||''//k1=v1;k2=v2;k3=v3cookieStr.split(';').forEach(item=>{if(!item){return}constarr=item.split('=')constkey=arr[0].trim()constval=arr[1].trim()req.cookie[key]=val})nodejssetCookie//loginif(method==='POST'&&req.path==='/api/user/login'){const{username,password}=req?.bodyconstresult=login(username,password)returnresult.then(data=>{if(data.username){//操作cookieres.setHeader('SetCookie',`username=${data.username}`)returnnewSuccessModel()}returnnewErrorModel('loginfailed')})}6.4cookie限制设置httpOnlyres.setHeader('SetCookie',`用户名e=${data.username};路径=/;httpOnly`)//获取cookie过期时间constgetCookieExpires=()=>{constd=newDate()d.setTime(d.getTime()+(24*60*60*1000))console.log('d.toGMTString()is',d.toGMTString())returnd.toGMTString()}res.setHeader('Set-Cookie',`userid=${userId};path=/;httpOnly;expires=${getCookieExpires()}`)6.6sessioncookie会暴露username,很危险的userid,sid,conentid,对应服务器端的username。session直接是一个js变量,放在nodejs进程内存中;如果内存太大,多个进程之间会挤压进程的空间,无法共享数据。工具。web服务器最常用的缓存数据库,数据保存在内存中,读写速度比mysql快,但是比较贵,断电丢失。一个单独的服务只是与nodejs的调用关系。就像mysql一样,所以不会出现人满为患的情况。多个进程之间访问同一个redis。所以会话将被同步。Redis可以扩展。即使用户数量增加,也可以增加机器,并且可以扩展成一个集群。session对性能要求极高,因为每次都要发送请求。掉电也没关系,重新登录即可。所以不能直接存入mysql。6.9constredis=require('redis');const{REDIS_CONF}=require('../conf/db');//创建客户端constredisClient=redis.createClient(REDIS_CONF);redisClient.on('error',(error)=>{console.log(error);})functionset(key,val){if(typeofval==="object"){val=JSON.stringify(val);}redisClient.set(key,val,redis.print);}functionget(key){constpromise=newPromise((resolve,reject)=>{redisClient.get(key,(err,val)=>{如果(err){reject(err)return}if(val==null){resolve(null);返回}try{resolve(JSON.parse(val))}catch(ex){resolve(val)}resolve(val);})});returnpromise;}module.exports={set,get}setmynamemjgetmyname//mjget*//获取所有keyvalue//获取sessionreq.sessionId=userIdget(req.sessionId).then(sessionData=>{if(sessionData==null){//在redis中初始化会话值set(req.sessionId,{})//设置会话req.session={}}else{//设置会话req.session=sessionData}//console.log('req.session',req.session)//处理发布数据returngetPostData(req)}).then(postData=>{.....}6.14为什么要用nginx,因为前端启动的服务和nodejs启动的服务不是同一个端口,cookie不跨域共享,使用http-server启动一个前端服务,端口设置to8001.nodejs:port8000everyone去8080端口。6.15高性能web服务器nginx),开源,免费如果你请求/根目录,请求html,那么nginx直接返回,返回html如果你请求/api/blog/...先到nginx的8000端口,再到node服务的端口,8001。这种对客户端不可见的代理称为反向代理。使用easyconnect连接,称为正向代理。客户端可以控制测试配置文件格式是否正确:ngnix-tstartnginxrestartnginx-sreloadstopngnix-sstopsudovi/usr/local/etc/nginx/nginx.conf主要是添加这几句代码,然后注释掉上面的一些。location/{proxy_pass
