node.js 基础(含mongodb,express,express-art-template)
node.js入门笔记
文章目录
- 1.Node.js
- 1.1 JavaScript开发弊端
- 1.2 node.js模块化开发规范
- 1.3 module.exports和exports
- 2.系统模块
- 2.1 什么时系统模块
- 2.2 系统模块fs文件操作
- 读取文件内容
- 写入文件内容
- 2.3 系统模块path路径操作
- 为什么要路径拼接
- 路径拼接语法
- 2.4相对路径vs绝对路径
- 2.5系统模块http创建网站服务器模块
- 2.6系统模块url解析地址模块
- 2.7系统模块querystring转化参数为对象
- 3 获取第三方模块
- 3.1第三方模块nodemon
- 3.2第三方模块nrm
- 3.3第三方模块Gulp
- Gulp能做什么
- Gulp使用
- Gulp提供的方法
- Gulp插件
- 4. package.json
- node_modules文件夹问题:
- 项目依赖
- 开发依赖
- package-lock.json文件的作用
- 5.node.js模块加载机制
- 5.1模块查找规则-当模块拥有路径但没有后缀时
- 5.2模块查找规则-当模块没有路径且没有后缀时
- 6.服务器端基础概念
- 创建web服务器(http模块)
- HTTP协议
- HTTP协议概念
- 报文
- 请求报文
- 响应报文
- 请求参数
- 路由
- 静态资源
- 动态资源
- 获取静态资源类型插件 mime
- node.js异步编程
- 同步api,异步api
- 同步API异步API区别 (获取返回值)
- 回调函数
- 同步api和异步api的区别(代码执行顺序)
- 代码执行顺序
- node.js异步api
- promise解决异步函数回调地狱问题
- 异步函数 async/await
- async关键字
- await
- 数据库
- 为什么使用数据库
- 数据库相关概念
- node操作mongodb 下载第三方包 mongoose
- 连接数据库
- 创建集合
- 创建文档
- 导入数据
- 查询文档
- 删除文档
- 更新文档
- mongoose验证
- 集合关联
- 案例:用户信息的增删查改 user
- 模板引擎
- 第三方模块art-template 模板引擎
- 模板语法
- 输出
- 原文输出
- 条件判断
- 循环
- 子模版
- 模板继承
- 模板配置
- 第三方模块dateformat时间格式化
- 案例
- 案例: 第三方模块router
- 第三方模块 serve-static
- Express框架
- express框架特性
- 中间件
- app.use中间件用法
- 中间件应用
- 错误处理中间件
- 捕获错误
- Express请求处理
- 模块化路由
- GET参数获取
- POST参数获取
- Express路由参数
- 静态资源的处理
- express-art-template模板引擎
- app.locals对象
1.Node.js
1.1 JavaScript开发弊端
JavaScript使用时存在两大问题,文件依赖和命名冲突
1.2 node.js模块化开发规范
- node.js规定一个JavaScript就是一个模块,模块内部定义的变量和函数默认情况下在外部无法得到
- 模块内部可以使用exports对象进行成员导出,使用require方法导入其他模块
1.3 module.exports和exports
两者相等,指向同一个引用地址,如果module.exports和exports都进行了修改,最终以module.exports为准
2.系统模块
2.1 什么时系统模块
node运行环境提供的API,因为这些Api都是以模块化方式进行开发的,所以又称node运行环境的api为系统模块
2.2 系统模块fs文件操作
node中的回调函数都是错误函数,第一个参数为报错信息,第二个时数据,如果没有错,第一个参数为null
读取文件内容
fs.readFile(‘文件路径/文件名称’,[编码格式],callback)
// 导入文件模块
const fs = require('fs');
// node,读写文件也有同步和异步的接口
fs.readFile('hello.txt', {flag: 'r',encoding: "utf-8"
},(err,data)=>{if(err){console.log(err)}else{console.log(data)}})
console.log(content);
写入文件内容
fs.writeFile(“文件按路径/文件名称”,‘数据’,callback)
// 导入文件模块
const fs = require('fs');
fs.writeFile('./demo.txt','即将写入的内容',err=>{if(err!=null){console.log(err);return;}console.log("文件内容写入成功")
})
2.3 系统模块path路径操作
为什么要路径拼接
- 不统操作系统的路径分隔符不统一
- /public/uploads/avatar
- Windows上是\ 反斜杠
- Linux上是/
路径拼接语法
path.join(“路径”,“路径”,…)
const path = require("path")
const finalPath = path.join("public",'uploads','avatar')
console.log(finalPath)//public\uploads\avatar
2.4相对路径vs绝对路径
- 大多数情况下使用绝对路径,因为相对路劲有时候相对的是命令行工具的当前工作目录
- 在读取文件或设置文件路劲都会选择绝对路劲
- 使用__dirname获取当前文件所在的绝对路径
// 拼接成绝对路径
const path = require('path')
let info2 = path.join(__dirname,'sxt','qianduan')
2.5系统模块http创建网站服务器模块
// 创建网站服务器模块
const http = require("http")
// app对象就是网站服务器对象
const app = http.createServer()
// 当客户端有请求来的时候
app.on("request", (req, res) => {//req为请求的,res为响应// 根据请求执行对应的事件
})
// 监听端口
app.listen(3000)
console.log("服务器端口已启动,使用localhost:3000访问");
2.6系统模块url解析地址模块
const url = require('url')
//url.parse(要解析的url地址,true(将查询参数(query)解析成对象形式))
let {query,pathname} = url.parse(req.url,true)
2.7系统模块querystring转化参数为对象
const querystring = require("querystring")
app.on("request", (req, res) => {// post 参数是通过事件的方式接受的//data 当请求参数传递的时候触发data事件//end 当参数参数完成时触发end事件let postParams = ''req.on("data",params=>{// 将获取到的params参数拼接在一起postParams += params})req.on('end',()=>{let queryPa = querystring.parse(postParams)console.log(querystring.parse(postParams));console.log(queryPa.username);})res.end('ok')
})
3 获取第三方模块
npm(node package manager):node 的第三方模块管理工具
- 下载:npm install 模块名称
- 卸载:npm unintall package模块名称
全局安装和本地安装
- 命令行工具:全局安装
- 库文件:本地安装
3.1第三方模块nodemon
nodemon是一个命令行工具,用于辅助项目开发
在node。js中,每次修改文件都要在命令行工具中重新执行,很繁琐
使用步骤
- npm install nodemon -g
- 在命令行工具中用nodemon命令替代node命令 (nodemon index.js 执行文件,会在终端挂起,代码修改时保存会自动重新执行)
3.2第三方模块nrm
nrm: npm下载地址切换工具
npm默认的下载地址在国外,国内下载速度慢
使用步骤
- npm install nrm -g下载他
- 查询可用下载地址列表nrm ls
- 切换npm下载地址 nrm use 下载地址名称(nrm use taobao)
3.3第三方模块Gulp
基于node平台开发的前端构建工具
将机械化操作编写成任务,想要执行机械化操作时执行一个命令行命令任务就能自动执行
Gulp能做什么
- 项目上线,html,css,js文件压缩
- 语法转换(es6,less…)
- 公共文件抽离
- 修改文件浏览器自动刷新
Gulp使用
- 使用npm install gulp
- 在项目根目录简历gulpfile.js文件
- 重构项目的文件夹结构src目录放置源代码文件,dist目录放置构建后的文件
- 在gulpfile.js文件编写任务
- 在命令行工具中执行gulp任务
Gulp提供的方法
- gulp.src() 获取文物要处理的文件
- gulp.dest() 输出文件
- gulp.task() 建立gulp任务
- gulp.watch() 监控文件的变化
基本使用
npm install gulp-cli -g
终端执行gulp 任务名(task) 执行任务
// 不做异步处理或加dom,会报错The following tasks did not complete: first Did you forget to signal async completion?// 引用gulp模块
const gulp = require("gulp")
// 使用gulp.task建立任务
// 1. 任务的名称
// 2. 任务的回调函数
// gulp.task("first", async() => {
// console.log("第一个gulp任务执行了");
// // 1. 使用gulp.src 获取要处理的文件
// await gulp.src("./src/css/index.css")
// .pipe(gulp.dest('dist/css'))
// })
//gulp 4.0 的任务函数中,如果任务是同步的,需要使用 done 回调。这样做是为了让 gulp 知道你的任务何时完成。
gulp.task("first", (done) => {console.log("第一个gulp任务执行了");// 1. 使用gulp.src 获取要处理的文件gulp.src("./src/css/index.css").pipe(gulp.dest('dist/css'))done()
})
Gulp插件
插件网址
- gulp-htmlmin:html文件压缩 html文件压缩使用方法
- gulp-csso :压缩css
- gulp-babel :JavaScript语法转化
- gulp-less:less语法转化
- gulp-uglify:压缩混淆JavaScript
- gulp-file-include 公共文件包含
- browsersync 浏览器实时同步
npm install 插件名
引入插件,看官网插件使用
gulp-file-include使用方法:
- 吧公共代码提取出来放置到common文件夹
- 源代码处使用@@include("./common/xxx")引入
- gulpfile.js中使用插件即可
4. package.json
node_modules文件夹问题:
1.文件过多,将项目整体拷贝给别人,传输速度太慢
2. 复杂的模块依赖关系需要被记录,确保模块的版本和当前保持一直
项目根目录npm init -y初始化package.json文件夹
下载的依赖都会记录在dependencies中,只需执行npm install就能把需要的依赖下载好
npm install 所有依赖都下载好
npm install product 只下载项目依赖
项目依赖
- 在项目开发阶段和现上运营阶段,都需要依赖的第三方包,称为项目依赖,会记录在dependencies
// package.json里的"dependencies": {"formidable": "^1.2.2","mime": "^2.4.6"}
开发依赖
- 在项目开发阶段需要,吸纳上运营阶段不需要依赖的第三方包,成为开发依赖
- 使用npm install 包名 --save-dev命令将包添加到package.json文件的devDependencies字段中
// package.json
//scripts别名 "build"命令替换原来的nodemon app.js命令。npm run build执行"scripts": {"test": "echo \"Error: no test specified\" && exit 1","build","nodemon app.js"},"devDependencies": {"gulp": "^4.0.2"}
package-lock.json文件的作用
- 锁定包的版本,确保再次下载时不会因为包版本不同而产生问题
- 加快下载速度,因为该文件中已经记录项目所依赖第三方包的树状结构和包的下载地址,重新安装时只需下载即可,不需要额外的工作
5.node.js模块加载机制
5.1模块查找规则-当模块拥有路径但没有后缀时
require(’./find.js’)
require(’./find’)
- require方法根据模块路径查找模块,如果时完整路径,直接引入模块
- 如果模块后缀省略,先找同名js文件再找文件夹
- 如果找到了同名文件夹,找文件夹中的index.js
- 如果文件夹中没有index.js就回去当前文件夹中的package.js文件中查找main选项中的入口文件
- 如果找指定的入口文件不存在或者没有指定入口文件就会报错,模块没有找到
5.2模块查找规则-当模块没有路径且没有后缀时
require(‘find’)
- node.js会假设他是系统模块
- node.js会去node_modules文件夹中
- 首先是否有该名字的js文件
- 再看是否有该名字的文件夹
- 如果时文件夹看是否有index.js
- 如果没有index.js查看该文件夹中package.json中的main选项确定模块入口文件
- 找不到报错
6.服务器端基础概念
URL组成
传输协议:服务器ip或域名:端口/资源所在位置表示,一般端口默认8080会省略
http://www.itcast.cn/index.html
http: 超文本传输协议,提供了一种发布和接收html页面方法
创建web服务器(http模块)
// 创建网站服务器模块
const http = require("http")
// app对象就是网站服务器对象
const app = http.createServer()
// 当客户端有请求来的时候
app.on("request",(req,res)=>{//req为请求的,res为响应res.end('<h2>hello user</h2>')
})
// 监听端口
app.listen(3000)
console.log("服务器端口已启动,使用localhost:3000访问");
HTTP协议
HTTP协议概念
超文本传输协议,规定如何从网站服务器传输文本到本地浏览器,基于客户端服务器架构工作,是客户端(用户)和服务器端(网站)请求和应答标准
报文
在HTTP请求和响应的过程中传递的数据块就叫报文,包括要传送的数据和一些附加信息,并且要遵守好规定的格式
客户端->服务器端 请求报文(请求方式(post),请求地址)
服务器端-> 客户端 响应报文(内容类型(text/html),内容长度)
请求报文
- 请求方式
- get 请求数据
- post 发送数据
- 请求地址
app.on("request", (req, res) => {// 获取请求方式,console.log(req.method)// 获取请求地址req.url// 获取请求报文req.headers}if(req.url=='/index'||req.url=="/"){res.end("<h2>welcome to homepage欢迎来到首页</h2>")}else if(req.url=='/list'){res.end("welcome to list")}else{res.end("no find")}if(req.method=='GET'){res.end("GET请求")}else if(req.method==='POST'){res.end("post请求")}
}
响应报文
- HTTP状态码
- 200 请求成功
- 404请求资源没有找到
- 500 服务器端错误
- 400 客户端请求有语法错误
- 内容类型
- text/html
- text/css
- application/javascript
- image/jpeg
- application/json
http.on("request",(req,res)=>{res.writeHead(200,{// 默认content-type ,纯文本// "content-type":'text/plain'// 设置为text/html就能看到返回的html代码效果了"content-type":'text/html;charset=utf8'})if(req.url=='/index'||req.url=="/"){res.end("<h2>welcome to homepage欢迎来到首页</h2>")}
}
请求参数
客户端向服务器发送请求携带的信息。
GET请求参数
- 参数被放置在浏览器地址栏中 如:http://localhost:3000/?name=zhangsan&age=20
POST请求参数
- 参数被放置在请求体中进行传输
- 获取post参数需要使用data事件和end事件
- 使用querystring系统模块将参数转换成对象格式
// 创建网站服务器模块
const http = require("http")
//处理请求参数模块 querystring,querystring.parse解析成对象形式
const querystring = require("querystring")
// app对象就是网站服务器对象
const app = http.createServer()
// 当客户端有请求来的时候
app.on("request", (req, res) => {// post 参数是通过事件的方式接受的//data 当请求参数传递的时候触发data事件//end 当参数参数完成时触发end事件let postParams = ''req.on("data",params=>{// 将获取到的params参数拼接在一起postParams += params})req.on('end',()=>{let queryPa = querystring.parse(postParams)console.log(querystring.parse(postParams));console.log(queryPa.username);})res.end('ok')
})
// 监听端口
app.listen(3000)
console.log("服务器端口已启动,使用localhost:3000访问");
路由
路由是由指客户端请求地址与服务器程序代码的对应关系,即请求什么响应什么
const http = require("http")
const url = require("url")
const app = http.createServer()
app.on("request", (req, res) => {res.writeHead(200, {"content-type": 'text/html;charset=utf-8'})const method = req.method.toLowerCase()const pathname = url.parse(req.url).pathnameif (method == 'get') {if (pathname == '/' || pathname=='/index') {res.end("<h1>欢迎来到首页")} else if (pathname == '/list') {res.end("<h1>欢迎来到列表页")} else {res.end("<h1>404网页已丢失")}}})
app.listen(3000)
console.log("服务开启,访问http://localhost:3000");
静态资源
服务器端不需要处理,可以直接响应给客户端的资源就是静态资源,如:CSS,JavaScript,image文件
动态资源
相同的请求地址不统的响应资源,这种资源就是动态资源
http://www.itcast.cn/article?id=1
http://www.itcast.cn/article?id=2
获取静态资源类型插件 mime
mime.getType(path)
const http = require("http")
const url = require("url")
const path = require("path")
const fs = require("fs")
const mime = require("mime")
const app = http.createServer()
app.on("request",(req,res)=>{let pathname = url.parse(req.url).pathnamepathname = pathname=="/"?'/3d.html':pathnameconst relPath = path.join(__dirname,"public",pathname)// 获取资源类型const type = mime.getType(relPath)// console.log(relPath);fs.readFile(relPath,(err,data)=>{if(err!=null){res.writeHead("404",{"content-type":"text/html;charset=utf-8"})res.end("<h1>访问失效")}else{res.writeHead("200",{"content-type":type})res.end(data)}})
})
app.listen(3000)
console.log("服务器已启动");
node.js异步编程
同步api,异步api
同步api:只有当前api执行完成,才能继续下一个api
异步api: 当前api的执行不会阻碍后续代码的执行
同步API异步API区别 (获取返回值)
同步API可以从返回值拿到api结果,异步不行
// 同步
function sum(n1,n2){return n1+n2
}
const result = sum(10,20) // 30
function getMsg(){setTimeout(function(){return{msg:'hello node.js'}},2000)// return undefined 函数默认会有个返回undefined
}
const msg = getMsg()
// 执行完异步函数时,msg已经输出的
console.log(msg); //undefined
回调函数
自己定义函数让别人调用
// 自己定义函数让别人调用
function getData(callback){}
//getdata函数调用
getData(()=>{})
同步api和异步api的区别(代码执行顺序)
同步api从上到下一次执行,前面的代码会阻塞后面的代码执行
for(var i=0;i<10000;i++){console.log(i)
}
console.log("for后面的代码")
// 会先执行for循环在输出
异步api不会等待api执行完成后再向下执行代码
console.log("代码开始执行")
setTimeout(()=>{console.log("2秒后执行")},2000)
setTimeout(()=>{console.log("0秒后执行")},0)
console.log("代码结束执行")
// 结果:代码开始执行,代码结束执行,0秒后执行,2秒后执行
代码执行顺序
先执行同步代码,遇到异步代码时先放置回调函数队列,同步代码执行完毕后,根据异步代码执行区去找到对应的回调函数队列里的异步函数,将其执行
node.js异步api
fs.readFile('./demo.txt',(err,result)=>{})
var server = http.creteServer()
server.on('request',(req,res)=>{})
promise解决异步函数回调地狱问题
let promise = new Promise((resolve,reject)=>{setTimeout(()=>{if(true){resolve("成功了")}else{reject("失败了")}},2000)
})promise.then(result=>console.log(result))
.cath(error=>console.log(error))
异步函数 async/await
async关键字
- 普通函数前加async关键字,变成异步函数
- 异步函数默认返回promise对象
- 在异步函数内部使用return关键字进行结果返回 结果会被包裹在promise中,return关键字替代了resolve方法
- 在异步函数内部使用throw关键字抛出程序异常
- 调用异步函数再链式调用then方法获取异步函数执行结果
- 调用异步函数再链式调用catch方法获取异步函数执行的错误信息
async function fn(){// async 会把函数编程异步函数,返回promise对象,return为原来的resolve方法return "成功"
}
fn().then((result)=>{console.log(result);
})
async function f2(){// throw为原来的reject方法throw "错误"
}
f2().then((result)=>{console.log(result);//不执行
}).catch(err=>{console.log(err);//返回了错误
})
await
- await只能出现在异步函数中
- await promise await后面只能写promise对象
- await关键字可暂停异步函数向下执行,直到promise返回结果
相当于封装了一个new Promise()方法
let fs = require("fs")
let promisify = require("util").promisify
// 改造现有异步函数api让其返回promise对象 从而支持异步函数语法
let readFile = promisify(fs.readFile)
async function run(){let r1 = await readFile("1.txt","utf-8")let r2 = await readFile(r1+".txt","utf-8")let r3 = await readFile(r2+".txt","utf-8")
}
run()
数据库
为什么使用数据库
- 动态网站的数据都是存储在数据库中
- 数据库可以用来持久存储客户端通过表单收集的用户信息
- 数据库软件本身可以对软件进行高效管理
数据库相关概念
在一个数据库软件中可以包含多个数据库,在每个数据仓库中可以包含多个数据集合,每个数据集中中可以包含多条文档(具体数据)
术语 | 解释说明 |
---|---|
database | 数据库,mongoDB数据库软件可以建立多个数据库 |
collection | 集合,一组数据的集合,可以理解为JavaScript中的数组 |
document | 文档,一条具体的数据,可以理解为JavaScript中的对象 |
field | 字段,文档中的属性名称,可以理解为JavaScript中的对象属性 |
使用mongoDB下载好mongodb后,进入bin文件,执行命令行 mongod --dbpath E:\web前端总学习\Node学习\软件\datapack 开启mongod,就可以使用图形化工具连接数据库了
node操作mongodb 下载第三方包 mongoose
连接数据库
// 没有playground数据库会自动创建
const mongoose = require("mongoose")
mongoose.connect("mongodb://localhost/playground",{useNewUrlParser: true,useUnifiedTopology: true})
.then(()=>{console.log('数据库连接成功');
})
.catch(()=>{console.log('连接失败');
})
创建集合
创建集合分为两步,一是对集合设定规则,二是创建集合,创建mongoose.Schema构造函数的实例即可创建集合
创建文档
创建文档实际就是插入数据
分两步:
- 创建集合实例
- 调用实例对象下的save方法将数据保存到数据库中
let mongoose = require("mongoose")
mongoose.connect("mongodb://localhost/playground",{useNewUrlParser: true,useUnifiedTopology: true})
.then(()=>{console.log('数据库连接成功');
})
.catch(()=>{console.log('连接失败');
})// 设定集合规则
const courseSchema = new mongoose.Schema({name:String,author:String,isPublished:Boolean
})
// 创建集合并应用规则,接收的是构造函数
// 第一个参数为集合名称,第二参数为集合规则,在compass中会集合名称会自动加上s和变小写
const Course = mongoose.model("Course",courseSchema) //courses
// 创建文档
const course = new Course({name:'ljx2',author:'ali',isPublished:true
})
// 将文档插入到数据库
course.save()
向集合中插入数据的第二种方法
const Course = mongoose.model("Course",courseSchema)
Course.create({name:'ljx3',author:'第二种方法',isPublished:true},(err,data)=>{console.log(err);console.log(data);
})Course.create({name:'ljx3',author:'第二种方法',isPublished:true})
.then(data=>console.log(data))
.catch(err=>console.log(err))
导入数据
mongoimport -d 数据库名称 -c 集合名称 --file 要导入的文件
导入数组json时
使用mongoimport -d 数据库名称 -c 集合名称 --jsonArray 要导入的文件
查询文档
find()根据条件查找文档(条件为空则查找所有文档)
Course.find().then(result=>{console.log(result)})
// 查询用户集合中的所有文档
Course.find().then(result=>{console.log(result);})
// 根据条件查询
Course.find({name:"ljx"}).then(result=>{console.log(result);})
//返回文档(数组的形式)
[{_id: 5f9e95da33c7093398444d30,name: 'ljx',author: 'ali',isPublished: true,__v: 0}
]
findOne() 返回一个文档
//根据条件查询文档
Course.findOne({name:"ljx"}).then(result=>{console.log(result);})// 返回文档
{_id: 5f9e95da33c7093398444d30,name: 'ljx',author: 'ali',isPublished: true,__v: 0
}
- 匹配大小于
- $gt 大于 KaTeX parse error: Expected '}', got 'EOF' at end of input: … 小于 find({age:{gt:20,$lt:50}}).then(result=>{console.log(result)})
- 匹配包含$in
- 选择要查询的字段
字段前面加-代表不查询
select(‘name age -_id’) - 排序
sort(‘age’)
// 查询用户集合中的所有文档
test.find().then(result=>{console.log(result);})
// 根据大小与查询
test.find({age:{$gt:15,$lt:20}}).then(result=>console.log(result))
// 匹配包含
test.find({hobbies:{$in:["足球"]}}).then(result=>console.log(result))
// 需要查询的字段
test.find().select('name age -_id').then(result=>console.log(result))
// 排序,根据年龄升序排序,在字段名前加-降序排序
test.find().sort('-age').then(result=>console.log(result))
// skip(n)跳过n条数据,limit限制查询数量(分页的时候会用到)
test.find().skip(2).limit(3).then(result=>console.log(result))
删除文档
findOneAndDelete()
- 找到一条数据并删除
- 返回删除文档
- 如果匹配到多个文档,删除第一个匹配的文档
test.findOneAndDelete({name:'ljx2'}).then(result=>{console.log(result);})
deleteMany()
- 删除多个如果参数为空,会删除全部,返回一个对象,n删除条数,ok为1删除成功
test.deleteMany({hobbies:{$in:['排球']}}).then(result=>console.log(result))
更新文档
// 更新单个文档
// test.updateOne({查询条件},{要修改的值})
// test.updateOne({name:'ljx6'},{name:"梁非凡"}).then(result=>console.log(result))
// 更新多个文档
// test.updataMany({},{})
test.updateMany({age:{$gt:10}},{age:100}).then(result=>console.log(result))
mongoose验证
在创建集合规则时,可以设置当前字段的验证规则,验证失败则输入插入失败
- required:true 必传字段
- minlength:[2,“字符串长度不能超过2”],
- maxlength:[6,“字符串长度不能超过6”],
- trim:true
- min: 最小值
- max:最大值
- default: Date.now 设置默认时间
- enum:[‘html’,‘css’,‘node.js’] 枚举,只能传入这些值
- validate: 自定义验证器
let mongoose = require("mongoose")
mongoose.connect("mongodb://localhost/playground", {useNewUrlParser: true,useUnifiedTopology: true}).then(() => {console.log('数据库连接成功');}).catch(() => {console.log('连接失败');})// 设定集合规则
const postScheme = new mongoose.Schema({title: {type: String,required: [true, '请输入标题'],minlength: [2, "最小长度不能超过2"],maxlength: [6, "最大长度不能超过6"],// 去除空格trim: true},age: {type: Number,// 最小的值min: 18,// 最大的值max: [100, "最大年龄不能超过100"]},publishDate: {type: Date,// 设置默认值为当前时间default: Date.now},category: {type: String,// 枚举,列举出当前字段可以拥有的值enum: {values: ['html', 'css', 'javascript', 'node.js'],//返回错误的信息message: '分类名称不可用'}},// 自定义验证规则author: {type: String,validate: {validator: v => {// 返回布尔值// true验证成功// false验证失败// v 要验证的值return v && v.length > 4},message: '传入的值不符合验证规则'}}
})
const post = mongoose.model("Post", postScheme)
post.create({title: ' aaaaa ',age: 99,category: 'css',author: '吾无异于曹贼'
}).then(result => {console.log(result);
})
集合关联
通过不同集合的数据之间是有关系的,例如文章信息何用户信息存储在不同集合中,但文章是某个用户发布的,要查询文章的所有信息包括发布用户,需要用到集合关联
- 使用id对集合进行关联
- 使用populate方法进行关联集合查询
const mongoose = require("mongoose")
mongoose.connect("mongodb://localhost/playground", {useNewUrlParser: true,useUnifiedTopology: true}).then(() => {console.log('数据库连接成功');}).catch(() => {console.log('连接失败');})
// 用户规则
const userSchema = new mongoose.Schema({name:{type:String,required:[true,"请输入名字"]},age:{type:Number}
})
// 文章规则
const postSchema = new mongoose.Schema({title:{type:String},author:{type:mongoose.Schema.Types.ObjectId,ref:'User'}
})
// 用户集合
const user = mongoose.model('User',userSchema)
// 文章集合
const Post = mongoose.model("Post",postSchema)
// 创建用户
user.create({name:'ljx',age:'18'}).then(result=>console.log(result))
// 创建文章
Post.create({title:'发布的文章题目',author:'5f9f959b8ee81514206ea593'}).then(result=>console.log(result))
// Post.find().then(result=>console.log(result))
// 联合查询
Post.find().populate('author').then(result=>console.log(result))
案例:用户信息的增删查改 user
- 搭建网站服务器,实现客户端与服务器端的通信
- 连接数据库,创建用户集合,向集合中插入文档
- 当用户访问/list时,将所有用户信息查询出来
- 当用户信息和表格html进行拼接并将拼接结果响应回客户端
- 当用户访问/add时,呈现表单页面,并实现添加用户信息功能
- 当用户访问/modify时,呈现修改页面,并实现修改用户信息功能
- 当用户访问/delete时,实现用户删除功能
模板引擎
模板引擎是第三方模块。
让开发者更加友好地拼接字符串,是项目代码更加清晰,更加易于维护
第三方模块art-template 模板引擎
- npm install art-template
- const template = require(‘art-template’)引入模板引擎
- 告诉模板引擎要拼接的数据和模板在哪const html = template(‘模板路径’,数据)
模板语法
- art-template 同时支持两种语法:标准语法和原始语法
- 标准语法可以让模板更容易读写,原始语法具有强大的逻辑处理能力
标准语法:{{数据}}
原始语法:<%=数据%>
输出
将某项数据输出在模板中,标准语法和原始语法如下:
- 标准语法:{{数据}}
- 原始语法:<%=数据%>
原文输出
如果数据中携带html标签,默认模板引擎不会解析标签,会将其转义后输出
- 标准语法:{{@数据}}
- 原始语法:<%-数据%>
条件判断
标准语法{{if 条件 }}内容{{else if 条件}}内容{{else}}内容
{{/if}}
原始语法<%if(条件){%>内容
<%}else if(条件){%>内容
<%}>else {%>内容
<%}%>
<!-- 标准语法 -->{{if age > 18}}年龄大于18{{else if age < 15 }}年龄小于15{{else}}年龄不符合要求{{/if}}
// 原始语法<% if(age>18){%>年龄大于18<%} else if(age<15) {%>年龄小于15<%} else {%>年龄不符合要求<%}%>
循环
- 标准语法:{{each 数据}}{{/each}}
- 原始语法:<%for(){%><%}%>
<!--标准语法--><ul>{{each user}}<li>{{$index}}</li><li>{{$value.name}}</li><li>{{$value.age}}</li><li>{{$value.sex}}</li>{{/each}}</ul>
<!--原始语法--><ul><%for(var i = 0;i < user.length;i++){%><li><%= i%><%= user[i].name%><%= user[i].age%><%= user[i].sex%></li><%}%></ul>
子模版
使用子模版可以将网站的公共区块(头部,底部)抽离到单独的文件中。
- 标准语法:{{include ‘模板’}}
- 原始语法:<%include(‘模板’)%>
{{include './common/header.art'}}
<%include('./common/footer.art')%>
模板继承
使用模板继承可以将网站html骨架抽离到单独的文件中,其他页面模块可以继承骨架文件。
公共模块 layout.art 将html骨架抽离出来,并在需要填充的位置使用{{block ‘name’}}{{/block}}说明
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0">{{block 'title'}}{{/block}}{{block 'link'}}{{/block}}
</head>
<body>{{block 'content'}}{{/block}}
</body>
</html>
继承模板 05.art
extent '路径’继承模板
{{block}}内容{{/block}}填充模板
{{extend './common/layout.art'}}
{{block 'title'}}<title>测试标题</title>
{{/block}}
{{block 'content'}}{{msg}}
{{/block}}
{{block 'link'}}
<link rel="stylesheet" href="">
{{/block}}
模板配置
- 向模板导入变量 template.defaults.imports.变量名=变量值
- 设置模板根目录template.defaults.root = 模板目录
- 设置模板默认后缀 template.defaults.extname=’.art’
// 配置模板根目录
template.defaults.root = path.join(__dirname,"views")
// 导入模板变量
template.defaults.imports.dateFormat = dateFormat
// 配置模板默认后缀
template.defaults.extname = '.html'
const html = template(viewsPath, {time:new Date()
})
// 没有后缀时自动默认.html后缀
const html2 = template('06',{})
console.log(html);
console.log(html2);
第三方模块dateformat时间格式化
案例
制作流程
- 建立项目文件夹并生成项目描述文件
- 创建网站服务器实现客户端和服务端通信
- 连接数据库并根据需求设计学员信息表
- 创建路由并实现页面模板呈现
- 实现静态资源访问
- 实现学生信息添加功能
- 实现学生信息展示功能
案例: 第三方模块router
功能:实现路由
使用步骤:
- 获取路由对象
- 调用路由对象提供的方法创建路由
- 启动路由
const getrouter = require("router")
const router = getrouter()
router.get('/add',(req,res)=>{res.end()
}
app.on('request',(req,res)=>{router(req,res)
})
第三方模块 serve-static
功能:实现静态资源访问服务
步骤:
- 引入serve-static模块并获取创建静态资源服务功能的方法
- 调用方法创建静态资源服务并指定静态资源服务目录
- 启用静态资源服务功能
const serveStatic = require("serve-static")
// 实现静态访问服务
const serve = serveStatic(path.join(__dirname,'public'))
server.on('request',()=>{serve(req,res)
})
server.listen(3000)
添加学生信息功能步骤分析
- 再模板表单种指定请求地址和请求方式
- 为每一个表单添加name属性
- 添加实现学生信息功能路由
- 接收客户端传递过来的学生信息
- 将学生信息添加到数据库中
- 将页面重定向到学生信息列表页面
学生信息列表页面分析
- 从数据库中将所有学生的信息查询出来
- 通过模板引擎将学生信息和HTML模板进行拼接
- 将拼接好的html模块响应给客户端
Express框架
Express是一个基于node平台的web应用开发框架,它提供了一系列的强大特性,帮助你创建各种web应用。
使用npm install express下载
express框架特性
- 提供方便简洁的路由定义方式
- 对获取HTTP请求参数进行了简化处理
- 对模板引擎支持程度高,方便渲染动态HTML页面
- 提供了中间件机制有效控制HTTP请求
- 拥有大量第三方中间件对功能进行扩展
中间件
中间件就是一堆方法,可以接收客户端发来的请求,可以对请求做出响应,也可以将请求继续交给下一个中间件继续处理
中间件主要由两部分构成,中间件方法以及请求处理函数
中间件方法由express提供,负责拦截请求,请求处理函数由开发人员提供,负责处理请求
如:
app.get('请求路径','处理函数') //接收并处理get请求
app.post('请求路径','处理函数') //接收并处理post请求
可以针对同一个请求设置多个中间件,对同一个请求进行多次处理.
默认情况下,请求从上到下以此匹配中间件,一旦匹配成功,终止匹配.
可以调用next方法将请求的控制权交给下一个中间件,直到遇到结束请求的中间件
app.get('./request',(req,res,next)=>{req.name='张三';next()
})
app.get('./request',(req,res)=>{res.send(req.name)
})
app.use中间件用法
app.use 匹配所有的请求方式,可以直接传入请求处理函数,代表接收所有的请求。
注意:app.use中间件放在其他前面
app.use((req,res,next)=>{console.log("消息经过了use中间件");next()
})
// 加上参数地址时,表示只有该路径会触发该中间件
app.use('/request',(req,res,next)=>{res.send("消息经过了request")
})
中间件应用
- 路由保护,客户端在访问需要登录的页面时,可以先使用中间件判断用户登陆状态,未登录则拦截请求,直接响应禁止用户进入需要登录的页面
- 网站维护公告,在所有路由的最上面定义接收所有请求的中间件,直接为客户端做出响应,网站正在维护中
- 自定义404页面
const app = express()
// 网站公告,直接响应公告内容
app.use((req,res,next)=>{res.send("网站维护中。。。请于xxx时间段再访问")
})
// 拦截未登录用户
app.use((req,res,next)=>{let isLogin = trueif(isLogin){next()}else{res.send("请登录后再访问页面")}
})
app.get('/request',(req,res,next)=>{res.send("欢迎来到request页")
})
// 自定义404页面,放在最后面,等上面的中间件先判断完有没有符合的
app.use((req,res,next)=>{res.status(404).send("网页不存在")
})
错误处理中间件
程序执行的过程中,不可避免的会出现一些无法预料的错误,比如文件读取失败,数据库连接失败,错误处理中间件是一个集中处理错误的地方
当程序出现错误时,调用next()方法,将错误信息传递给next()方法,即可触发错误处理中间件
app.use((err,req,res,next)=>{res.status(500).send(err.message)
})
// 模拟异步请求发生错误,异步api的错误都是通过回调获取的
app.get('/list',(req,res,next)=>{fs.readFile('./2文件清单.txt','utf8',(err,result)=>{if(err!=null){// next带参数则作为程序错误next(err)}else{res.send(result)}})
})// 模拟同步请求错误
app.get('/index',(req,res)=>{throw new Error('程序发生了未知错误')
})
app.get("/request",(req,res)=>{res.send('正常访问')
})
// 错误中间件
app.use((err,req,res,next)=>{res.status(500).send(err.message)
})
捕获错误
再node.js中,异步api的错误信息都是通过回调函数获取的,支持promise对象的异步api发生错误可以通过catch方法获取。
try catch可以捕获异步函数以及其他同步代码再执行过程中发生的错误,但是不能其他类型的api(如回调函数)发生错误
const promisify = require("util").promisify
const readFile = promisify(fs.readFile)
// 模拟异步promise对象的异步api发生错误
app.get('/list',async (req,res,next)=>{try {await readFile('./2文件清单.txt')} catch (error) {next(error)}})// 错误中间件
app.use((err,req,res,next)=>{res.status(500).send(err.message)
})
Express请求处理
模块化路由
基础用法
const express = require("express")
// 创建网站服务器
const app = express()
// 创建路由对象
const home = express.Router()
// 为路由对象匹配添加路径
app.use('/home',home)
// 在home路由下创建二级路由
home.get('/index',(req,res)=>{res.send('欢迎来到首页')
})
app.listen(3000)
console.log('服务已启动');
构建模块化路由
home.js
const express = require("express")
const home = express.Router()
home.get('/index',(req,res)=>{res.send('欢迎来到home首页')
})module.exports = home
admin.js
const express = require("express")
const admin = express.Router()
admin.get('/index',(req,res)=>{res.send("欢迎来到admin主页")
})module.exports = admin
index.js
const express = require("express")
// 创建网站服务器
const app = express()
const home = require("./route/home")
const admin = require("./route/admin")
app.use('/home',home)
app.use('/admin',admin)
app.listen(3000)
console.log('服务已启动');
GET参数获取
Express框架使用req.query即可获取get参数,框架内部会将参数转换为对象并返回
const app = express()
app.get('/index',(req,res)=>{res.send(req.query)
})
POST参数获取
Express接收post请求参数需要借助第三方包 body-parser
//引入body-parser模块
const bodyParser = require("body-parser")
// 配置body-parser模块
// 拦截所有请求并调用方法处理请求参数
// extended:false 方法内部使用querystring模块处理请求参数的格式
//extended:true 方法内部使用qs处理请求参数的格式
app.use(bodyParser.urlencoded({extended:false}))
// 接收请求
app.post('/add',(req,res)=>{
// 获取post请求参数console.log(req.body)
})
Express路由参数
// 此时需要通过http://localhost:3000/index/123/ljx 来访问
// 前面req.query获取的参数形式是http://localhost:3000/index?id=123&&name:ljx
app.get('/find/:id/:name',(req,res)=>{res.send(req.params) //{"id":"123","name":"ljx"}
})
静态资源的处理
通过Express.static可以方便地托管静态文件
app.use(express.static('public')
const express = require("express")
const bodyParser = require("body-parser")
const path = require("path")
const app = express()
// 静态资源访问http://localhost:3000/css/list.css
// app.use(express.static(path.join(__dirname,'public')))
//静态资源访问http://localhost:3000/static/css/list.css
app.use('/static',express.static(path.join(__dirname,'public')))
app.listen(3000)
console.log("服务已启动");
express-art-template模板引擎
为了art-template和express框架配合使用而封装成的express-art-template
使用npm install art-template express-art-template 下载
// 当渲染后缀为art的模板时,使用expree-art-template
app.engine('art',require('expree-art-template'))
// 设置模板存放目录
app.set('views',path.join(__dirname,'views'))
// 渲染模板时 不写后缀 默认拼接art后缀
app.set('view engine','art');
app.get('/',(req,res)=>{// 渲染模板res.render('index')
})
const express = require('express')
const path = require("path")
const app = express()
// 1. 告诉express框架使用什么模板引擎渲染什么后缀的模板文件// 1. 模板后缀// 2. 使用的模板引擎
app.engine('art',require("express-art-template"))
// 2. 告诉express框架模板存放的位置 views为固定的配置名称
app.set("views",path.join(__dirname,'views'))
// 3. 告诉express框架模板的默认后缀是什么
app.set('view engine','art');
app.get('/index',(req,res)=>{res.render('index',{msg:'index page'})
})
app.get('/list',(req,res)=>{//render处理了以下内容// 1. 拼接模板路径// 2. 拼接模板后缀// 3. 哪一个模板和哪一个数据进行拼接// 4. 将拼接结果响应给客户端res.render('list',{msg:'list page'})
})
app.listen(3000)
console.log("服务已启动");
app.locals对象
将变量设置在这,所有的模板都能使用这个数据
app.locals.users = [{name:'张三',age:14
},{name:'李四',age:20
}]
index.art
{{msg}}
<ul>{{each users}}<li>{{$value.name}}</li><li>{{$value.age}}</li>{{/each}}
</ul>
index.js
const express = require('express')
const path = require("path")
const app = express()
// 1. 告诉express框架使用什么模板引擎渲染什么后缀的模板文件// 1. 模板后缀// 2. 使用的模板引擎
app.engine('art',require("express-art-template"))
// 2. 告诉express框架模板存放的位置 views为固定的配置名称
app.set("views",path.join(__dirname,'views'))
// 3. 告诉express框架模板的默认后缀是什么
app.set('view engine','art');
// 设置公共的对象
app.locals.users = [{name:'张三',age:14
},{name:'李四',age:20
}]
app.get('/index',(req,res)=>{res.render('index',{msg:'index page'})
})
app.get('/list',(req,res)=>{//render处理了以下内容// 1. 拼接模板路径// 2. 拼接模板后缀// 3. 哪一个模板和哪一个数据进行拼接// 4. 将拼接结果响应给客户端res.render('list',{msg:'list page'})
})
app.listen(3000)
console.log("服务已启动");
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 量子科技发展成国家议题 百度抢先布局锚定量子计算未来
文 | 曾响铃 来源 | 科技向令说(xiangling0815) 量子科技时代正在加速来了。 日前,国家就量子科技的发展强调道「要充分认识推动量子科技发展的重要性和紧迫性,加强量子科技发展战略谋划和系统布局,把握大趋势&…...
2024/4/25 2:44:25 - 华远37年沉浮:何以乘风破浪?何以行稳致远?
时间是一把标尺,历史是标尺上的刻度。 中国改革开放四十余年,涌现出无数优秀的企业,成就中国经济的腾飞。其中价值更在于,这些伴随时代成长的企业,都将成为历史卷书不可或缺的篇章。 唯有穿越周期,与时代…...
2024/4/25 2:48:57 - 【BUUCTF】第九天
1.[DDCTF2018](╯□)╯︵ ┻━┻ 打开是一串16进制数字符串的长度是134所以是两个一组 但是一组字符串的长度超过127于是用暴力破解这个移位密码 用python代码得到flag 2.sqltest 文件是pacp于是进行流量分析 发现是一个bool注入于是导出HTTP数据包得到注入查…...
2024/4/25 2:48:56 - DHCP介绍与实际应用
DHCP工作原理 dhcp动态主机配置协议 UDP协议:端口67:客户端。68:服务器端 用于为TCP/IP网络中的计算机自动分配TCP/IP参数的协议 优点 减少管理员的工作量 避免输入错误的可能 避免ip地址冲突 当更改IP地址段时,不需要重新配置每个用户的IP地址 提高了…...
2024/4/25 2:48:55 - Unity持续按键(持续按下)设置间隔时间,子弹连续发射间隔时间(萌新也能懂)
设置持续按键的间隔时间,解决手速问题(雾 通常在按键操作的游戏中,特别是发射子弹,都会有几种情况出现,一种是按下按键就发射一次,一种是一直按下按键就持续发射。但是在不仅是Unity里,java的按键检测中也同…...
2024/5/4 18:25:03 - java问题积累
文章目录[toc]Java基础知识点JVM内存划分类的五大成分四大修饰符方法的重载局部变量,成员变量,成员方法**什么是封装****什么是继承** extends**什么是多态****关联关系 has-a****依赖关系 use-a****对比this和super**static关键字**final关键字****抽象…...
2024/4/25 2:48:53 - vscode中关于eslint的各种报黄线错误
总结eslint各种报黄线错误提示 1.这些规则必须添加到eslintrc.js中 “no-alert”: 0, // 禁止使用alert confirm prompt“no-array-constructor”: 2, //禁止使用数组构造器“no-bitwise”: 0, //禁…...
2024/4/25 2:48:53 - 网联V2X测试解决方案
V2X测试的挑战 V2X,顾名思义就是vehicle-to-everything,通过现代通信与网络技术,实现车与人、车、路、后台等信息交换共享,从而帮助汽车实现安全、舒适、节能、高效行驶。 由于涉及到车与周围环境的通信交互,V2X的应…...
2024/4/25 2:48:51 - 2.图像的加载与保存
学习视频可参见pythonopencv3.3视频教学 基础入门 今天写的是图像,视频的加载与保存 1.图像,数字图像,像素 1.图像 图像:定义为二维函数f(x,y),其中,x,y是空间坐标,f(x,y)是点(x,yÿ…...
2024/4/25 2:48:51 - 京东双十一任务自动脚本(支持全民营业、热爱时光机)
转自:https://www.52pojie.cn/thread-1291731-1-1.html 目前可自动完成京东全民营业、热爱时光机活动中的所有任务 JS脚本代码: "ui";threads.start(function(){ui.run(function(){ui.layout(<vertical><frame id"bg" w&…...
2024/4/25 2:48:49 - 导电树脂胶水
➤ 01导电树脂胶水 使用 导电树脂胶 可以快速修复电子产品。比如:陶瓷电容粘接计算器计算机游戏机遥控器LED灯带电子琴薄膜按键开关按键开关电脑键盘笔记本键盘等等… 下面是购买到的导电树脂胶水:规格;7g ▲ 从淘宝网络购买到的导电树脂胶&…...
2024/4/25 2:48:49 - google gRPC在macOS中的简单使用
google gRPC在macOS中的简单使用 gRPC 官方文档中文版 1. 简述 A high-performance, open-source universal RPC framework gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc…...
2024/4/25 2:48:47 - 什么样的爬虫是非法的?
什么样的爬虫是非法的? 爬虫不能涉及个人隐私! 如果爬虫程序采集到公民的姓名、身份证件号码、通信通讯联系方式、住址、账号密码、财产状况、行踪轨迹等个人信息,并将之用于非法途径的,则肯定构成非法获取公民个人信息的违法行为。 另外&…...
2024/4/26 10:48:10 - 马上消费区块链BaaS平台通过国家网信办区块链信息服务备案
国家互联网信息办公室发布第四批境内区块链信息服务名称及备案编号,马上消费金融(简称“马上消费”)区块链BaaS平台通过备案。 国家网信办于2019年2月15日正式实施《区块链信息服务管理规定》以来,组织开展备案审核工作࿰…...
2024/4/25 2:44:36 - vivo预研6G背后的眼界和底气
5G刚起,6G已来。 据估计,5G大规模商用还需要3-4年。虽然5G距离普及还有很长的路要走,但国内已经有企 业提前展开了对6G的研究和探索工作。 10月23日,vivo通信研究院正式对外发布《6G愿景需求与挑战》和《数字生活 2030》6G系 列…...
2024/4/25 2:44:36 - 编程与修仙小说的联动
本人是一名程序人,和修仙小说爱好者,最近在日常编程,和摸鱼看小说的的生活中,将编程和修仙小说对应了起来。 首先是编程语言种类,编程语言总体分以为机器语言、汇编语言、高级语言,与复杂度区分正好对应了…...
2024/4/25 2:44:37 - VirtualBox之NAT网络使用配置
VirtualBox之NAT网络使用配置一. 写在之前二. VirtualBox四种网络模式连通性汇总列表三. VirtualBox之NAT网络1. 设置NAT网络模式2. 启动系统3. 关闭防火墙4. 查看网卡及网络IP5. 编辑网卡配置文件6. 重启网络7. 再次查看网卡及网络IP8. 验证…...
2024/5/8 4:00:42 - 【拼多多商家首选多多情报通】拼多多店铺诊断怎么做?拼多多店铺如何运营?
其实在拼多多上面想要运营好一家店铺,说容易也容易,说难也难,关键还是在于各位卖家们是否能够做好充分的准备工作,同时也要整理好思路,作为店铺的掌柜,还要站在宏观角度,整体布局。今天拼多多数…...
2024/4/25 2:44:40 - 【IoT】产品设计之结构工艺:锌合金表面处理及压铸件优缺点
1、锌合金压铸件是否需要表面处理 1.1、做表面处理场景 锌合金材质化学性能不稳定,所以在空气中易被氧化,发黑、或者发黄,如果锌合金压铸件是裸露在外面氧化后是会影响产品的美观度的。 一般产品是用在外面的,就需要做表面处理…...
2024/4/25 2:44:31 - 医学小知识 - 甲减患者如何正确服用优甲乐?关注这几点,助您破甲成蝶!
对于甲状腺疾病患者来说,“优甲乐”是再熟悉不过了,一旦做了甲状腺腺体切除术,或者其他原因引起的甲状腺功能减低症,往往就和“优甲乐”结下了不解之缘,甚至是“终生陪伴”。 优甲乐又名左甲状腺素钠片,用…...
2024/4/25 2:44:34
最新文章
- 如何使用IntelliJ IDEA SSH连接本地Linux服务器远程开发
文章目录 1. 检查Linux SSH服务2. 本地连接测试3. Linux 安装Cpolar4. 创建远程连接公网地址5. 公网远程连接测试6. 固定连接公网地址7. 固定地址连接测试 本文主要介绍如何在IDEA中设置远程连接服务器开发环境,并结合Cpolar内网穿透工具实现无公网远程连接…...
2024/5/9 22:16:39 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/9 21:23:04 - Python中大的一把锁
今天可以来讲解下GIL是个什么了。 GIL为什么是Python中大的一把锁? GIL是Global Interpreter Lock的缩写,翻译过来就是全局解释器锁。 从字面上去理解,它就是锁在解释器头上的一把锁,它使Python代码运行变得有序。 假如有一段…...
2024/5/6 22:04:06 - Docker Desktop+WSL2安装到自定义路径
现在大多数软件实在太“流氓”了,在安装过程中,根本不让你选择安装路径,默认安装到$HOME下(windows C盘),随着软件的使用增多,可能磁盘空间不够,这个时候就想着,看看某些…...
2024/5/9 19:14:38 - 考研数学|《1800》+《660》精华搭配混合用(经验分享)
肯定不行,考研数学哪有这么容易的! 先说说这两本习题册,李永乐老师推出的新版660题,相较于18年前的版本,难度略有降低,更加适合初学者。因此,对于处于基础阶段的学习者来说,新版660…...
2024/5/9 10:27:24 - 416. 分割等和子集问题(动态规划)
题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满ÿ…...
2024/5/8 19:32:33 - 【Java】ExcelWriter自适应宽度工具类(支持中文)
工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...
2024/5/9 7:40:42 - Spring cloud负载均衡@LoadBalanced LoadBalancerClient
LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...
2024/5/9 2:44:26 - TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案
一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...
2024/5/8 20:33:13 - VB.net WebBrowser网页元素抓取分析方法
在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...
2024/5/9 3:15:57 - 【Objective-C】Objective-C汇总
方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...
2024/5/9 5:40:03 - 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...
2024/5/9 7:40:40 - 【ES6.0】- 扩展运算符(...)
【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数࿰…...
2024/5/8 20:58:56 - 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?
文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...
2024/5/9 1:35:21 - Go语言常用命令详解(二)
文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...
2024/5/9 4:12:16 - 用欧拉路径判断图同构推出reverse合法性:1116T4
http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai 和 a i 1 a_{i1} ai1 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然࿰…...
2024/5/9 7:40:35 - 【NGINX--1】基础知识
1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...
2024/5/9 19:47:07 - Hive默认分割符、存储格式与数据压缩
目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...
2024/5/9 7:40:34 - 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法
文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...
2024/5/9 1:42:21 - --max-old-space-size=8192报错
vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...
2024/5/9 5:02:59 - 基于深度学习的恶意软件检测
恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...
2024/5/9 4:31:45 - JS原型对象prototype
让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...
2024/5/9 16:54:42 - C++中只能有一个实例的单例类
C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...
2024/5/8 9:51:44 - python django 小程序图书借阅源码
开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图࿰…...
2024/5/9 6:36:49 - 电子学会C/C++编程等级考试2022年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...
2024/5/9 4:33:29 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57