当前位置: 首页 > news >正文

Node.js入门指南(四)

目录

express框架

express介绍

express使用

express路由

express 响应设置

中间件

路由模块化 

EJS 模板引擎

express-generator


hello,大家好!上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识,这篇文章主要给大家分享Node.js中的express框架!

express框架

express介绍

在上几篇文章中我们介绍了如何使用http模块去搭建http请求,而在实际的开发中却很少直接使用它去搭建服务。一般都会借助express框架去进行开发。express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs.com.cn/ express 相当于是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)。

express使用

express 本身是一个 npm 包,所以我们可以通过 npm 来进行安装。先对文件进行初始化:npm i,然后再使用npm i express来进行安装express。它的基本使用如下,通过node(nodemon) index.js执行文件之后,我们在浏览器通过访问:http://127.0.0.1:9000/home来进行访问结果。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建get请求
app.get('/home',(req,res)=>{res.end('hello express');
});
//监听端口
app.listen(9000,()=>{console.log('服务启动!')
})

express路由

有学习过vue的小伙伴对路由应该不陌生,express中的路由也是同样的道理,通过访问不同的路径来得到不同的模块,在此之前我们是通过判断语句来实现访问不同路径返回对应内容的。而路由能够更加简便地来实现相应的功能。

一个路由包括请求的方法,请求的路径以及回调函数三个部分组成。回调函数接收请求的对象以及相应的对象两个参数。使用all可以适用于所有的请求方式,而路径使用 * 一般用于处理请求路径匹配不到的错误。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建get请求
app.get('/home',(req,res)=>{res.end('hello express');
});
//创建post请求
app.post('/login',(req,res)=>{res.end('login success');
});
//首页路由
app.get('/',(req,res)=>{res.end('home');
})
//匹配所有请求方法
app.all('/search',(req,res)=>{res.end('all req');
})
//定义404路由
app.all('*',(req,res)=>{res.end('<h1>404 Not Found</h1>')
})
//监听端口
app.listen(9000,()=>{console.log('服务启动!')
})

我们仍然可以使用express来获取到请求报文中的数据。express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式。它除了具有原生的method、url、httpVersion以及headers等操作以外,它还可以直接使用req.path来得到请求的路径,以及req.query来得到查询的数据,并且是以对象形式输出。调用get()方法还可以直接传入自己想要的特定响应头进行输出。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建get请求
app.get('/request',(req,res)=>{//原生操作console.log(req.method);//GETconsole.log(req.url);///request?name=N-Aconsole.log(req.httpVersion);//1.1console.log(req.headers);//express操作console.log(req.path);///requestconsole.log(req.query);//{ name: 'N-A' }//获取ipconsole.log(req.ip);//::ffff:127.0.0.1//获取特定的请求头console.log(req.get('host'));//127.0.0.1:9000res.end('hello express');
});//监听端口
app.listen(9000,()=>{console.log('服务启动!')
})

路由参数的获取对我们很重要,我们需要通过用于输入的不同的路由参数来匹配出不同的数据,但如果我们一个一个去添加路由规则的话是不现实的。这时候我们可以使用路由参数,在传参的位置我们使用一个占位符,:字符串。字符串的位置在发请求时随意写什么都可以进行匹配到。同时我们可以使用req.params.id来获取我们的路由参数,通过判断获取到的路由参数来返回不同的结果。

//导入express
const express=require('express');
//创建应用对象
const app=express();
//创建路由
app.get('/:id.html',(req,res)=>{console.log(req.params.id);res.end('goods detail');
})//监听端口
app.listen(9000,()=>{console.log('服务启动!')
})

可能有点难理解,我们来做一个小练习体验一下吧!现在有个需求,通过用于在浏览器输入不同的请求路径,在json文件中会匹配到对应的数据进行展示。先将两个水果的数据放在一个json文件中,然后当用于输入http:127.0.0.1:9000/friut/1.html时在页面上显示id为1的水果的描述以及图片,http:127.0.0.1:9000/friut/2.html时显示id为2的水果。

//json文件
{"friut":[{"id":1,"name": "沃盼(WOPAN)四川眉山脐橙新鲜水果橙子2kg 4斤装","dicPrice": "¥19.9","oriPrice": "¥50","src":"https://ts1.cn.mm.bing.net/th/id/R-C.efa51c1248bc80a2bd2bc9a1c2449fad?rik=f%2f53DOukVylGvg&riu=http%3a%2f%2fn.sinaimg.cn%2fsinakd20210207s%2f296%2fw1030h866%2f20210207%2f09f4-kirmaiu8306791.jpg&ehk=eTr6szTDThqmZdwt5x3V45f%2b%2bRNJFsDuBjDBLFY99fY%3d&risl=&pid=ImgRaw&r=0"},{"id":2,"name": "智利原装进口车厘子礼盒装JJ级 约2kg 果径约28-30mm 原箱礼盒装 新鲜水果","dicPrice": "¥219","oriPrice": "¥299","src":"https://img.zcool.cn/community/0165435d9c740da801211d530e7b5e.jpg@1280w_1l_2o_100sh.jpg"}]
}
//index.js//导入express
const express = require('express');//导入json文件
const { friut } = require('./data.json');//创建应用对象
const app = express();
//创建路由
app.get('/friut/:id.html', (req, res) => {//获取路由参数let { id } = req.params;//在数组中寻找对应的id的数据let result = friut.find(item => {if (item.id === Number(id)) {return true;}});//判断if(!result){res.statusCode=404;res.end(`<h1>404 Not Found</h1>`)}res.end(`<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><h2>${result.name}</h2><img src="${result.src}"/></body></html>`);
})//监听端口
app.listen(9000, () => {console.log('服务启动!')
})

要点就是通过获取到路由的参数来进行相应数据的寻找以及匹配。

express 响应设置

express可以对相应的数据进行相应的设置,框架封装了一些 API 来方便给客户端响应数据,并且兼容原生 HTTP 模块的获取方式。主要有res.status( )用于设置状态码,res.set()用于设置响应头,res.send()用于设置响应体,使用该方法设置响应体会自动将响应体中的内容转为utf-8的格式,直接写入中文不会出现乱码,因此无需再进行响应头的设置。同时几个方法还可以进行连贯操作。

const express=require('express');
const app=express();
app.get('/response',(req,res)=>{//原生响应设置res.statusCode=404;res.statusMessage='Not Find';res.setHeader('name','N-A');res.write('hello');res.end('response');//express响应res.status(200);res.set('name','N-A');res.send('你好呀')res.status(200).set('name','N-A').send('你好呀');
});app.listen(9000,()=>{console.log('服务已经启动!');
})

同时express还可以进行其他的响应设置,比如跳转响应、下载响应、JSON响应、响应文件的内容等。具体的实现效果自行实践。

const express=require('express');
const app=express();
app.get('/response',(req,res)=>{//跳转响应res.redirect('https://baidu.com');//下载响应res.download(__dirname+'./data.json');//JSON响应res.json({name:'N-A',study:'Node.js'})//响应文件内容res.sendFile(__dirname+'/index.html')
});app.listen(9000,()=>{console.log('服务已经启动!');
})

中间件

中间件(Middleware)本质是一个回调函数中间件函数可以像路由回调一样访问 请求对象(request) , 响应对象(response)。它的作用就是使用函数封装公共操作,对代码进行简化。它包括:全局中间件以及路由中间件。全局中间件每一个请求到达服务端之后都会执行全局中间件函数,而路由中间件只对某一些路由进行功能的封装。

全局中间件的实例如下,全局中间件函数三个参数,req,res以及next。next用于接续执行。使用中间件需要调用app.use()。

const express=require('express');
const app=express();
const fs=require('fs');
const path=require('path');
//声明中间件函数
function recordMiddleware(req,res,next){let {url,ip}=req;//将信息保存在文件中fs.appendFileSync(path.resolve(__dirname,'./access.log'),`${url} ${ip}\r\n`);next();
}//使用中间件函数
app.use(recordMiddleware);app.get('/home',(req,res)=>{res.send('首页')
});
app.get('/detail',(req,res)=>{res.send('详情页')
});
app.listen(9000,()=>{console.log('服务已经启动!');
})

路由中间件的实例如下,无需关注具体实现的功能,主要认识路由中间件如何使用,后续要实现什么功能,函数里面替换成对应的操作即可。它的使用方式与全局中间件不一样。它需要到对应的路由中进行添加。

const express=require('express');
const app=express();
const fs=require('fs');
const path=require('path');
//声明中间件函数
function checkCodeMiddleware(req,res,next){if(req.query.code==='521'){next();}else{res.send('错误');}
}app.get('/home',checkCodeMiddleware,(req,res)=>{res.send('首页')
});
app.get('/detail',checkCodeMiddleware,(req,res)=>{res.send('详情页')
});
app.all("*",(req,res)=>{res.send('<h1>404</h1>')
})
app.listen(9000,()=>{console.log('服务已经启动!');
})

静态资源来前几篇文章我们已经有介绍到了,对于静态资源的处理也是比较麻烦,需要获取对应文件的后缀名来判断该文件属于哪一种资源,再做相应的处理。而静态资源中间件可以大大地提高我们处理静态资源的效率。使用方式如下:

//引入express框架
const express = require('express');
//创建服务对象
const app = express();
//静态资源中间件的设置,将当前文件夹下的public目录作为网站的根目录
app.use(express.static('./public')); //当然这个目录中都是一些静态资源
//如果访问的内容经常变化,还是需要设置路由
//但是,在这里有一个问题,如果public目录下有index.html文件,单独也有index.html的路由,
//则谁书写在前,优先执行谁
app.get('/index.html',(request,response)=>{
respsonse.send('首页');
});
//监听端口
app.listen(3000,()=>{
console.log('3000 端口启动....');
});

静态资源中间件index.html为默认打开的资源,如果静态资源与路由规则同时匹配,谁先匹配谁就响应。路由响应动态资源,静态资源中间件响应静态资源

最后我们再介绍一个中间件:body-parser。express可以使用这个中间件来进行处理请求体。首先需要使用:npm i body-parser 进行安装。然后需要导入body-parser包,再获取中间件函数,最后是使用 request.body 来获取请求体数据。

我们以一个实例来展示吧,假设我们通过get请求来向本地的/login路径发请求,显示表单网页,通过post请求访问/login来获取表单中的用户名以及密码。

//index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><form action="/login" method="post">用户名:<input type="text" name="username"><br/>密码  :<input type="password" name="password"><br/><button>登录</button></form></body>
</html>
//导入express
const express=require('express');
//导入body-parser包
const bodyParser = require('body-parser');
//创建应用对象
const app=express();//处理 JSON 格式的请求体
//let jsonParser = bodyParser.json();//处理 querystring 格式的请求体
let urlParser = bodyParser.urlencoded({extended:false});
//创建路由规则
app.get('/login',(req,res)=>{res.sendFile(__dirname+'/index.html');
});
//post规则
app.post('/login',urlParser,(req,res)=>{console.log(req.body);res.send(req.body)
})
//监听端口
app.listen(9000,()=>{console.log('服务启动!')
})

路由模块化 

当什么需要对多个路由进行设置时,都在主文件中进行设置就会非常乱,维护起来也不是很好,因此express引入了Router,它可以实现路由的模块化,更好地进行管理路由。express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。

//创建单独的管理文件homeRouter.js//1. 导入 express
const express = require('express');
//2. 创建路由器对象
const router = express.Router();
//3. 在 router 对象身上添加路由
router.get('/', (req, res) => {
res.send('首页');
})
router.get('/cart', (req, res) => {
res.send('购物车');
});
//4. 暴露
module.exports = router;//主文件
const express = require('express');
const app = express();
//5.引入子路由文件
const homeRouter = require('./routes/homeRouter');
//6.设置和使用中间件
app.use(homeRouter);
app.listen(9000,()=>{
console.log('服务已经启动');
})

EJS 模板引擎

EJS 是一个高效的 Javascript 的模板引擎,模板引擎是分离 用户界面和业务数据 的一种技术。简单地将就是它能够实现我们的html文件以及js文件分离。上面那个路由跳转不同水果的案例我们就把html中的文件写到了js里面。因此使用EJS模板引擎可以让两者进分开。

首先我们需要使用:npm i ejs --save来进行安装。它是将变量名使用<%= 变量名 %>的形式包裹起来的。那具体怎么样体现它的分离效率呢?

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h2><%= name %>今天学习<%= study %></h2></body>
</html>
//导入EJS
const ejs=require('ejs');
const fs=require('fs');
//字符串
let name='N-A';
let study='Node.js'
//声明变量
let str=fs.readFileSync('./index.html').toString();
//使用ejs渲染
let result=ejs.render(str,{name,study});
console.log(result);

这样就可以完全将两者进行拆分,后续想要修改或者增加都是可以实现的。

下面再来演示EJS模块列表的渲染以及条件的渲染。都是使用<% %>将内容或者操作包裹在里面,然后变量仍然使用<%= %>来进行包裹。

//进行列表的渲染
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><ul><% study.forEach(item=>{ %><li><%= item %></li><% })%></ul></body>
</html>
//导入EJS
const ejs=require('ejs');
const fs=require('fs');const study=['Node.js','Vue.js','ES6','Webpack']
//声明变量
let str=fs.readFileSync('./index.html').toString();
//使用ejs渲染
let result=ejs.render(str,{study});
console.log(result);//输出
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><ul><li>Node.js</li><li>Vue.js</li><li>ES6</li><li>Webpack</li></ul></body>
</html>

下面展示条件渲染:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><% if(isLogin) { %><span>欢迎回来</span><% }else{ %><span>请登录</span><% } %></body>
</html>
//导入EJS
const ejs=require('ejs');
const fs=require('fs');let isLogin=true;
//声明变量
let str=fs.readFileSync('./index.html').toString();
//使用ejs渲染
let result=ejs.render(str,{isLogin});
console.log(result);//当isLogin为true是会输出欢迎回来,当为false时会显示请登录

那express如何使用EJS模板引擎呢?首先需要设置模板引擎,其次要设置模板文件的存放位置,然后通过render()方法来做响应,该方法接受两个参数:模板的文件名以及数据。最后再去设置的相应位置下去创建模板文件,后缀应该是.ejs。

//index.js//导入express
const express=require('express');
const app=express();
const path=require('path');
//设置模板引擎
app.set('view engine','ejs');
//设置模板文件的存放位置
app.set('views',path.resolve(__dirname,'./views'));app.get('/home',(req,res)=>{//render响应let name='N-A';res.render('home',{name});res.end('hello express');
})
//监听端口
app.listen(9000,()=>{console.log('服务启动!')
})
<!-- home.ejs --><!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><h1><%= name  %></h1></body>
</html>

express-generator

在我们练习的过程中express框架的代码都是我们一点一点写的,但是在实际的开发中会非常地低效,而express官方提供了一个工具express-generator,可以帮助我们快速搭建应用的骨架。

首先我们使用npm install -g express-generator命令来进行安装。然后可以通过express -h来查看它的相关命令。我们选择ejs模板引擎来进行创建。输入expres -e 文件名。创建之后先对文件进行初始化,npm init 以及npm i。之后运行npm start 打开3000端口,看到如下图片则表示成功!

创建之后的文件内容可以自己研究研究,这里就不做过多的解释!

好了,本文就好这里结束啦!感谢阅读~~

相关文章:

Node.js入门指南(四)

目录 express框架 express介绍 express使用 express路由 express 响应设置 中间件 路由模块化 EJS 模板引擎 express-generator hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了Node.js的模块化以及包管理工具等知识&#xff0c;这篇文章主要给大家分享Nod…...

Java LeetCode篇-深入了解关于数组的经典解法

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 轮转数组 1.1 使用移位的方式 1.2 使用三次数组逆转法 2.0 消失的数字 2.1 使用相减法 2.2 使用异或的方式 3.0 合并两个有序数组 3.1 使用三指针方式 3.2 使用合…...

LeeCode前端算法基础100题(4)- 无重复字符的最长子串

一、问题详情&#xff1a; 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2: 输入: s "bbbbb…...

Axios简单使用与配置安装-Vue

安装Axios npm i axios main.js 导入 import Axios from axios Vue.prototype.$axios Axios简单发送请求 get getTest() {this.$axios({method: GET,url: https://apis.jxcxin.cn/api/title?urlhttps://apis.jxcxin.cn/}).then(res > {//请求成功回调console.log(res)}…...

【初始前后端交互+原生Ajax+Fetch+axios+同源策略+解决跨域】

初始前后端交互原生AjaxFetchaxios同源策略解决跨域 1 初识前后端交互2 原生Ajax2.1 Ajax基础2.2 Ajax案例2.3 ajax请求方式 3 Fetch3.1 fetch基础3.2 fetch案例 4 axios4.1 axios基础4.2 axios使用4.2.1 axios拦截器4.2.2 axios中断器 5 同源策略6 解决跨域6.1 jsonp6.2 其他技…...

C语言--每日选择题--Day24

第一题 1. 在C语言中&#xff0c;非法的八进制是&#xff08; &#xff09; A&#xff1a;018 B&#xff1a;016 C&#xff1a;017 D&#xff1a;0257 答案及解析 A 八进制是0&#xff5e;7的数字&#xff0c;所以A错误 第二题 2. fun((exp1,exp2),(exp3,exp4,exp5))有几…...

记一次简单的PHP反序列化字符串溢出

今天朋友给的一道题&#xff0c;让我看看&#xff0c;来源不知&#xff0c;随手记一下 <?php // where is flag error_reporting(0); class NFCTF{ public $ming,$id,$payload,$nothing;function __construct($iii){$this->ming$ii…...

找工作面试技巧

问题描述&#xff1a;找工作时&#xff0c;不知道如何回答问题怎么办。 问题解决&#xff1a;可以尝试使用STAT原则来回答问题。具体如下。 "STAR" 原则是一种常用于回答面试问题的方法&#xff0c;特别是在描述个人经验、解决问题或展示技能和能力时。"STAR&q…...

Jackson无缝替换Fastjson

目录 文章目录 一&#xff0c;Fastjson到Jackson的替换方案方案代码序列化反序列化通过key获取某种类型的值类型替换 二&#xff0c;Springboot工程中序列化的使用场景三&#xff0c;SpringMVC框架中的Http消息转换器1&#xff0c;原理&#xff1a;2&#xff0c;自定义消息转换…...

JVM 内存分析工具 MAT及实践

线程分析工具 MAT 官网下载地址&#xff1a;http://www.eclipse.org/mat/downloads.php mat百度网盘链接&#xff1a;&#xff08;速度更快&#xff09; 链接&#xff1a;https://pan.baidu.com/s/1tMp8MQIXuPtg9zBgruO0Ug?pwdjqtv 提取码&#xff1a;jqtv jdk17 百度网盘链接…...

jupyter notebook 不知道密码,怎么登录解决办法

jupyter notebook 不知道密码&#xff0c;怎么登录解决办法 1、 windows下&#xff0c;打开命令行&#xff0c;输入jupyter notebook list &#xff1a; C:\Users\tom>jupyter notebook list Currently running servers: http://localhost:8888/?tokenee8bb2c28a89c8a24d…...

软著项目推荐 深度学习中文汉字识别

文章目录 0 前言1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xf…...

WEB渗透—反序列化(七)

Web渗透—反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩哔_…...

牛客网刷题笔记四 链表节点k个一组翻转

NC50 链表中的节点每k个一组翻转 题目&#xff1a; 思路&#xff1a; 这种题目比较习惯现在草稿本涂涂画画链表处理过程。整体思路是赋值新的链表&#xff0c;用游离指针遍历原始链表进行翻转操作&#xff0c;当游离个数等于k时&#xff0c;就将翻转后的链表接到新的链表后&am…...

【数据结构】图<简单认识图>

对于下面的内容&#xff0c;大家着重观察和理解图即可&#xff0c;可以直接绕过一些文字性的概念&#xff0c;对图有一个大概的认识。 图 简单认识图图的定义有向图和无向图完全图无向完全图有向完全图 图的基本存储结构邻接矩阵存储邻接矩阵的优点 网络的邻接矩阵邻接表无向图…...

Git介绍和基础命令解析

Git基本操作指令 工作区和暂存区 Git管理的文件分为&#xff1a;工作区(本地的文件夹)&#xff0c;版本库(.git文件夹)&#xff0c;版本库又分为暂存区stage和暂存区分支master(仓库) 工作区>>>>暂存区>>>>仓库 git add把文件从工作区>>>…...

力扣hot100 和为 K 的子数组 前缀和

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f37b; AC code class Solution {public int subarraySum(int[] nums, int k){int ans 0;int n nums.length;int[] s new int[n 1];// 前缀和s[0] 0;s[1] nums[0];for (int i 2; i < n; i)s[i] s[i - 1] nums[i - 1…...

6.12找树左下角的值(LC513-M)

算法&#xff1a; 这道题适合用迭代法&#xff0c;层序遍历&#xff1a;按层遍历&#xff0c;每次把每层最左边的值保存、更新到result里面。 看看Java怎么实现层序遍历的&#xff08;用队列&#xff09;&#xff1a; /*** Definition for a binary tree node.* public clas…...

【精选】框架初探篇之——MyBatis的CRUD及配置文件

MyBatis增删改查 MyBatis新增 新增用户 持久层接口添加方法 void add(User user);映射文件添加标签 <insert id"add" parameterType"com.mybatis.pojo.User">insert into user(username,sex,address) values(# {username},# {sex},# {address}) <…...

ES8语法async与await

async和await两种语法结合可以让异步代码像同步代码一样。 一、async函数 async函数的返回值为Promise对象promise对象的结果由async函数执行的返回值决定 async function fn() {// 返回一个字符串return 字符串&#xff1b;// 返回的结果不是一个Promise类型的对象&#xf…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...