nodejs - express 学习笔记

express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址:https://www.expressjs. com.cn/
简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)

一、初体验

// 1、导入 express 模块
const express = require('express')
// 2、创建应用对象
const app = express()
// 3、创建路由
app.get('/home', (req,res) => {res.end('hello express')
})
// 4、监听端口,启动服务
app.listen(3000, () => {console.log('服务启动成功....')
})

命令行执行该脚本

node <文件名> 
# 或者 
nodemon <文件名>

二、路由

1、什么是路由

官方定义: 路由确定了应用程序如何响应客户端对特定端点的请求

2、路由的使用

一个路由的组成有 请求方法 , 路径 和 回调函数 组成
express 中提供了一系列方法,可以很方便的使用路由,使用格式如下:
app.<method>(path,callback)

// 引入 express 模块
const express = require('express')
//  创建 express 应用
const app = express()
// 创建路由
app.get('/home', (req,res) => {res.end('hello express')
})
app.get('/', (req,res) => {res.end('home')
})
app.post('/login', (req,res) => {res.end('login')
})
// all 表示匹配所有方法:get、post等
// 只匹配路径,
app.all('/test', (req,res) => {res.end('test')
})
// 路径匹配不上时,就匹配 *
app.all('*', (req,res) => {res.end('404 not Found')
})// 监听端口
app.listen(3000, () => {console.log('服务已经启动....')
})

3、获取请求参数

express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式

// http://127.0.0.1:3000/request?name=zs&age18const express = require('express')const app = express()app.get('/request', (req,res) => {// console.log(req.method) // GET// console.log(req.url)  // /request?name=zs&age18// console.log(req.httpVersion)  // 1.1// console.log(req.headers)  // {}// express 操作// console.log(req.path) // /request// console.log(req.query)  // { name: 'zs', age18: '' }// console.log(req.ip) // ::ffff:127.0.0.1// 获取请求头console.log(req.get('host'))  // 127.0.0.1:3000res.end('request')
})app.listen(3000, () => {console.log('服务已经启动')
})

4、获取路由参数

路由参数指的是 URL 路径中的参数(数据)
通过 req.params 获取

app.get('/:id.html', (req,res) => {console.log(req.params.id)res.setHeader('content-type', 'text/html;charset=utf-8')res.end(`商品详情---商品id为${req.params.id}`)
})

5、路由参数练习

访问 http://127.0.0.1:3000/singer/id.html,根据 id 不同显示不同人员对信息
singers.json

{"singers": [{"singer_name":"周杰伦","singer_pic":"https://tse4-mm.cn.bing.net/th/id/OIP-C.MBdWohb239f-DDL1hTOD1gHaFj?rs=1&pid=ImgDetMain","other_name":"Jay Chou","singer_id": 4342,"id": 1},{"singer_name":"林俊杰","singer_pic":"https://ts1.cn.mm.bing.net/th/id/R-C.88bd5be6d420729a8c2522cea088dbba?rik=k6VZw%2bb%2bOra%2beA&riu=http%3a%2f%2fpic.baike.soso.com%2fp%2f20130105%2f20130105232231-1799387588.jpg&ehk=YSa6clxTqIwRP5wPGj6JGXPfHacZlaS9wPieFXYoi0U%3d&risl=&pid=ImgRaw&r=0","other_name":"JJ Lin","singer_id": 233,"id": 2},{"singer_name":"邓紫棋","singer_pic":"https://ts1.cn.mm.bing.net/th/id/R-C.1b542de55345409e9d43876f6ee1cb63?rik=SSmPaHF5CsAUxA&riu=http%3a%2f%2fn.sinaimg.cn%2fsinakd20110%2f120%2fw1080h1440%2f20220718%2f8dc6-218cc21c8f91db792bf3166bc3da4de4.jpg&ehk=gossNEDToapx2%2f7lhVLnyfLQta8zoXHzwgqVnDpSR%2fg%3d&risl=&pid=ImgRaw&r=0","other_name":"Cloria Tang","singer_id": 343,"id": 3}]
}

路由参数练习.js

const express = require('express')const { singers } = require('./singers.json')const app = express()app.get('/singer/:id.html', (req, res) => {let singer = singers.find(item => {return item.id === Number(req.params.id)})if(!singer) {res.statusCode = 404res.end('404 not Found')return}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><h1>${singer.singer_name}</h1><img src="${singer.singer_pic}" alt="" width="200"></body></html>`)
})
app.listen(3000, () => {console.log('服务已经启动....')
})

6、设置一般响应

const express = require('express')
const app = express()app.get('/response', (req, res) => {// 原生响应// 设置状态码// res.statusCode = 404// // 设置状态信息// res.statusMessage = 'not Found'// // 设置请求头// res.setHeader('xxx', 'yyy')// // 设置响应体// // res.write('hello express')、// // 设置响应体// res.send('你好')// 设置响应体// res.end('response')// express  响应// 设置状态码// res.status(500)// // 设置请求头// res.set('aaa', 'bbb')// // 设置响应体(会自动设置 Content-Type)// res.send('你好 express')// express 设置响应也可以链式调用res.status(500).set('aaa','bbb').send('你好啊 express')
})app.listen(3000, () => {console.log('服务已经启动....')
})

7、设置其他类型

const express = require('express')const app = express()
app.get('/other', (req, res) => {// 其他响应// 设置重定向 302// res.redirect('https://www.jd.com/')// 下载响应(里面放绝对路径)// res.download(__dirname+'/package.json')// JSON 响应,会自动设置 json 对应的响应头// res.json({//   name: 'zs',//   age: 18// })// 响应文件内容res.sendFile(__dirname + '/index.html')// 这里的响应,不需要再用 res.end() 结束
})app.listen(3000, () => {console.log('服务已经启动成功....')
})

三、express 中间件

1、概念

中间件Middleware本质是一个回调函数。
中间件函数可以像路由回调一样访问 请求对象、响应对象。
好像是 vue2 中的路由守卫

2、作用

使用函数封装公共操作,简化代码

3、类型

  • 全局中间件(类似于全局路由守卫)
    每次访问路由,都会先经过中间件,然后经过路由
  • 路由中间件(类似于独享路由守卫)
    访问具体的路由时,会先经过 路由中间件,再经过路由

以坐火车流程来举例,全局中间件就好像是 进站口,每个人都需要经过进站口,路由中间件 就好像是某一趟车的闸机口,只有这一趟车的人才会经过这个闸机口。

4、全局中间件

每一个请求 到达服务端之后 都会执行全局中间件函数

  1. 首先定义中间件函数 fn,接收3个参数:req、res、next(函数)
  2. 通过 app.user(fn) 应用中间件
let recordMiddleware = function(request,response,next){ //实现功能代码 //..... //执行next函数(当如果希望执行完中间件函数之后,仍然继续执行路由中的回调函数,必须调用next) next(); 
}app.use(recordMiddleware)
app.use(recordMiddleware2)
const express = require('express')
const fs = require('fs')
const path = require('path')const app = express()// 声明中间件函数
function recordMiddleware(req, res, next) {// 获取 url、iplet { url, ip } = req// 将信息保存在文件 access.log 中 fs.appendFileSync(path.resolve(__dirname, './access.log'), `${url}   ${ip}\r\n`)// 调用 next(这里如果不调用 next,后续的路由回调不会正常执行)next()
}
// 使用中间件函数
app.use(recordMiddleware)
app.get('/home', (req, res) => {res.end('home')
})
app.get('/admin', (req, res) => {res.end('admin')
})
app.all('*', (req, res) => {res.end('404 not Found')
})
app.listen(3000, () => {console.log('服务已经启动...')
})

5、路由中间件

如果 只需要对某一些路由进行功能封装 ,则就需要路由中间件
app.get('/路径','中间件函数',(request,response)=>{ });

/* 针对 /admin   /setting 的请求,要求 URL 携带 code= 521 参数,如未携带提示   暗号错误
*/const express = require('express')
const app = express()// 定义路由中间件
const checkCodeMiddleware = (req, res, next) => {if(req.query.code === '521') {next()} else {res.send('暗号错误')}
}
// 在需要校验的路由上,添加路由中间价
app.get('/admin', checkCodeMiddleware, (req, res) => {res.send('admin')
})
app.get('/setting', checkCodeMiddleware, (req, res) => {res.send('setting')
})
app.listen(3000, () => {console.log('服务已经启动.....')
})

6、讲台资源中间件

预习:nodejs

// 创建一个 HTTP 服务,端口 9000,满足如下需求:
// GET   /index.html       响应  page/index.html       的文件内容
// GET   /css/app.css      响应  page/css/app.css      的文件内容
// GET   /images/logo.png  响应  page/images/logo.png  的文件内容const http = require('http')
// 加载 fs 模块处理文件
const fs = require('fs')
// 加载 path 模块处理文件名、后缀
const path = require('path')
// 常用的 请求头
const mime = {html: 'text/html', css: 'text/css', js: 'text/javascript', png: 'image/png', jpg: 'image/jpeg', gif: 'image/gif', mp4: 'video/mp4', mp3: 'audio/mpeg', json: 'application/json'
}const server = http.createServer((request, response) => {let { pathname } = new URL(request.url, 'http://127.0.0.1:9000')if(request.method !== 'GET') {response.statusCode = 405response.end('<h1>405 Method Not Allowed</h1>')}fs.readFile(`${__dirname}/page${pathname}`, (err, data) => {// 读取文件失败后的处理if(err) {response.setHeader('content-type','text/html;charset=utf-8')switch (err.code) {case 'ENOENT':response.statusCode = 404response.end('<h1>404 NotFound</h1>')break;case 'EPERM':response.statusCode = 403response.end('<h1>403 Forbidden</h1>')break;default:response.statusCode = 500response.end('<h1>500 Internal Server Error</h1>')break;}return}// 获取文件后缀,如:htmllet ext = path.extname(pathname).slice(1)if(ext === 'html') {response.setHeader('content-type', `${mime[ext]};charset=utf-8`)} else {response.setHeader('content-type', mime[ext])}response.end(data)})})
server.listen('9000', () => {console.log('服务已经启动....')
})

express 内置处理静态资源的中间件

const express = require('express')
const app = express()// express 有内置的静态资源中间件,只需要设置一下资源目录
app.use(express.static(__dirname + '/public'))
//如果访问的内容经常变化,还是需要设置路由 
//但是,在这里有一个问题,如果public目录下有index.html文件,单独也有index.html的路由, 
//则谁书写在前,优先执行谁app.get('/home', (req,res) => {res.end('home')
})  
app.listen(3000, () => {console.log('服务启动成功....')
})

注意事项:

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

7、获取请求体数据 body-parser 中间件

第一步:安装
npm i body-parser

第二步:导入 body-parser 包
const bodyParser = require('body-parser');//处理 querystring 格式的请求体 
let urlParser = bodyParser.urlencoded({extended:false})); 
//处理 JSON 格式的请求体 
let jsonParser = bodyParser.json()
// 第四步:设置路由中间件,然后使用 request.body 来获取请求体数据
app.post('/login', urlParser, (request,response)=>{ //获取请求体数据 //console.log(request.body); //用户名 console.log(request.body.username); //密码 console.log(request.body.userpass); response.send('获取请求体数据'); });

获取到的请求体数据:[Object: null prototype] { username: 'admin', userpass: '123456' }

四、Router

1、概念

express 中的 Router 是一个完整的中间件和路由系统,可以看作是一个小型的 app 对象。

2、作用

对路由进行模块化,更好的管理路由。

3、使用

创建独立的 JS 文件(homeRouter.js)

// 1、导入 express
const express = require('express')
// 2、创建路由器对象
const router = express.Router()
// 3、在 router 对象上添加路由
router.get('/home', (req, res) => {res.send('前台首页')
})
router.get('/search', (req, res) => {res.send('搜索首页')
})
// 暴露 router 对象
module.exports = router

主文件 index.js

const express = require('express')
// 引入子路由文件
const adminRouter = require('./routes/adminRouter')
const homeRouter = require('./routes/homeRouter')const app = express()
// 设置和使用中间件
app.use(adminRouter)
app.use(homeRouter)// app.get('/home', (req, res) => {
//   res.send('前台首页')
// })// app.get('/search', (req, res) => {
//   res.send('搜索页面')
// })// app.get('/admin', (req, res) => {
//   res.send('后台首页')
// })// app.get('/setting', (req, res) => {
//   res.send('设置页面')
// })app.all('*', (req, res) => {res.send('404 Not Found')
})app.listen(3000, () => {console.log('服务已经启动....')
})

五、EJS 模板引擎

1、什么是模板引擎

模板引擎是分离 用户界面和业务数据 的一种技术。

2、什么是EJS

EJS 是一个高效的 Javascript 的模板引擎。
官网: https://ejs.co/
中文站:https://ejs.bootcss.com/

3、初体验

下载安装 EJS
npm i ejs --save
代码:

const ejs = require('ejs')
const fs = require('fs')const country = '中国'
// const str = `我爱你 ${country}`// const str = ejs.render('我爱你 <%= country %>', {country})
const file = fs.readFileSync(__dirname + '/01-初体验.html').toString()
const name = 'zhangsan'
const str = ejs.render(file, {country, name})console.log(str)

01-初体验.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><h1>我爱你 <%= country %></h1><h2>来自 <%= name %></h2>
</body>
</html>

4、常用语法

执行JS代码
<% code %>
输出转义的数据到模板上<%= code %>
输出非转义的数据到模板上<%- code %>

练习:

4-1、列表渲染

02-列表渲染.js

const fs = require('fs')
const ejs = require('ejs')
const xiyou = ['唐僧', '孙悟空', '猪八戒', '沙僧']// 1、js 模板字符串
// let html = '<ul>'// xiyou.forEach(item => {
//   html += `<li>${item}</li>`
// })
// html += '</ul>'// 2、ejs 直接拼标签
// let html = ejs.render(`<ul>
//     <% xiyou.forEach(item => { %>
//       <li> <%= item %> </li>
//     <% }) %>
// </ul>`, {xiyou})// 3、读取 html 文件,ejs 将数据传给 html
let file = fs.readFileSync(__dirname + '/02-列表渲染.html').toString()
let html = ejs.render(file, { xiyou })
console.log(html)

02-列表渲染.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><ul><% xiyou.forEach(item => { %><li><%= item %></li><% }) %></ul>
</body>
</html>
4-2、条件渲染
/* 通过 isLogin 决定最终的输出内容true    输出 <span>欢迎回来</span>flase   输入 <button>登录</button>  <button>注册</button>
*/const ejs = require('ejs')
let isLogin = false
// let html
// // 原生 js
// if(isLogin) {
//   html = `<span>欢迎回来</span>`
// } else {
//   html = `<button>登录</button>  <button>注册</button>`
// }let html = ejs.render(`<% if(isLogin) { %><span>欢迎回来</span><% } else { %><button>登录</button>  <button>注册</button><% } %>`, {isLogin})console.log(html)

5、express 中使用 ejs

  1. 创建一个目录(views)用来存放模板(以 ejs 结尾)
  2. 路由上使用
    在这里插入图片描述
const express = require('express')
const path = require('path')const app = express()
// 1、设置模板引擎
app.set('view engine','ejs'); 
app.engine('ejs', require('ejs').__express);
// 2、设置模板文件存放位置, 模板文件:具有模板语法内容的文件
app.set('views', path.resolve(__dirname, './views'))app.get('/home', (req, res) => {let title = '使用 ejs 模板渲染'// 3、render 响应// res.render('模板的文件名', '书库')res.render('home', { title })// res.send('你好啊')
})
app.listen(3000, () => {console.log('服务已经启动过成功')
})

6、express- generator 工具

它是 express 应用程序生成器,通过 express- generator 可以快速创建一个应用的骨架(类似与 vue 中的 vue-cli)。

6-1、下载

npm install -g express-generator

6-2、使用

express -e 目录名XXX 创建目录 XXX,这个目录 添加了 ejs 模板引擎的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/51148.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MOE模式:或将是最好的大模型应用开发路径

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 基于Dify的智能分类方案&#xff1a;大模型结合KNN算法&#xff08;附代码&#xff…

TiDB-从0到1-sync-diff-inspector数据校验工具

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCCTiDB-从0到1-部署篇TiDB-从0到1-配置篇TiDB-从0到1-集群扩缩容TiDB-从0到1-数据导出导入TiDB-从0到1-BR工具 一、sync-diff-inspector工具 sync-diff-inspector是TiDB原生…

3.仓颉编程_没有switch_case需使用match_case

仓颉编程_没有switch_case需使用match_case 支持两种 match 表达式&#xff0c;一种是包含待匹配值的 match 表达式&#xff0c;另一种是不含待匹配值的 match 表达式。 含有匹配值的 match 表达式 main() {let a Hello World!//不可变量var a2 var b 77 //可变变量match(b…

指针!!C语言(第三篇)

目录 一. 二维数组传参的本质 二. 函数指针变量和函数指针数组 三. typedef关键字 四. 转移表 五. 回调函数以及qsort使用举例 一. 二维数组传参的本质 &#x1f35f;首先我们先回顾一下二维数组是怎样传参的&#xff1f;我们需要传入数组名以及行数和列数&#xff0c;这…

Spring Boot|如何实现 Spring Boot 的优雅停机

文章目录 概述优雅停机的重要性实现优雅停机的方法1. 使用Spring Boot Actuator配置使用 2. 自定义Shutdown Hook示例代码 3. 使用Spring Boot 2.3及更高版本的优雅停机特性配置 4. 通过Spring Cloud Gateway和Ribbon示例配置 5. 定制化停机逻辑示例代码 最佳实践结论 概述 在…

Dhtmlx Gantt教程:创建交互式甘特图的完整指南

在现代的项目管理中&#xff0c;时间是一种宝贵的资源&#xff0c;而甘特图则是一把解锁项目进度的魔法钥匙&#xff0c;想象一下&#xff0c;您可以在一个直观而动态的时间轴上&#xff0c;清晰地看到项目的每一个任务如何交织在一起&#xff0c;如何随着时间的推移展开&#…

【优质精选】12节大模型系列教学课程之二:RAG 原理与应用

课程二&#xff1a;RAG 原理与应用 12节大模型系列教学课程之二&#xff1a;RAG 原理与应用 课程详细内容RAG 技术的基础知识RAG 的工作原理RAG 提高生成质量和准确性的原理RAG 在问答系统中的应用RAG 在文本创作中的应用RAG 在其他领域的应用探索RAG 技术的挑战与应对策略RAG …

代码随想录算法训练营【动态规划篇】

动态规划 注&#xff1a;本文代码来自于代码随想录 509. 斐波那契数 力扣509 Python 动态规划&#xff08;版本一&#xff09; class Solution:def fib(self, n: int) -> int:# 排除 Corner Caseif n 0:return 0# 创建 dp table dp [0] * (n 1)# 初始化 dp 数组dp[0]…

LangChain4j-RAG高级-检索增强器

Retrieval Augmentor 检索增强器 RetrievalAugmentor 是 RAG 管道的入口点。它负责使用从各种来源检索的相关 Content 来扩充 ChatMessage 。 可以在创建 AiService 期间指定 RetrievalAugmentor 的实例&#xff1a; Assistant assistant AiServices.builder(Assistant.cla…

探索大型语言模型LLama 2:原理揭秘与代码实践

一、引言 1.1 大型语言模型的重要性 大型语言模型作为人工智能领域的重要研究方向&#xff0c;近年来取得了显著的成果。这些模型在自然语言处理、机器翻译、对话系统、文本生成等领域展现了强大的能力&#xff0c;为人类带来了诸多便利。大型语言模型的出现&#xff0c;使得…

初识git工具~~上传代码到gitee仓库的方法

目录 1.背景~~其安装 2.gitee介绍 2.1新建仓库 2.2进行相关配置 3.拉取仓库 4.服务器操作 4.1克隆操作 4.2查看本地仓库 4.3代码拖到本地仓库 4.4关于git三板斧介绍 4.4.1add操作 4.4.2commit操作 4.4.3push操作 5.一些其他说明 5.1.ignore说明 5.2git log命令 …

ElementPlus轮播图-Vue3

注意&#xff1a;安装时建议使用手机热点&#xff0c;wifi不稳定&#xff0c;会出现执行不成功的现象。 安装 使用包管理器 # 选择一个你喜欢的包管理器# NPM npm install element-plus --save# Yarn yarn add element-plus# pnpm pnpm install element-plus引入配置 完整引…

视频主题Qinmei 3.0视频站源码_WordPress影视视频主题/附详细安装教程

Qinmei 3.0主题主要是将 wordpress 改造成纯 api 的站点&#xff0c;以便实现前后端分离的技术栈&#xff0c;目前的进度已经大致完成&#xff0c;唯一的问题就是需要安装 JWT token 插件。 功能介绍&#xff1a; 支持豆瓣以及 bangumi 的一键获取信息, 豆瓣 api 目前使用的是…

【Node.js基础05】包的理解与使用

一&#xff1a;包的理解与简介 1 什么是包 包是一个将模块、代码、以及其他资料聚合成的文件夹 2 包的分类 项目包&#xff1a;编写项目代码的文件夹 软件包&#xff1a;封装工具和方法供开发者使用 3 为什么要在软件包中编写package.json文件 记录包的清单信息 二&…

NSIS打包脚本第二篇

NSIS打包脚本 NSIS打包脚本第一篇 字符串提取过滤 WordFind 使用方法 ${WordFind} "[string]" "[delimiter]" "[E][options]" $varoption解读 +1和+01一样,代表分割后的第一个字符串 +表示从左往右,-表示从右向左 +2}} 表示从左到右,前2…

Matlab arrayfun 与 bsxfun——提高编程效率的利器!

许多人知道 MATLAB 向量化编程&#xff0c;少用 for 循环 可以提高代码运行效率&#xff0c;但关于代码紧凑化编程&#xff0c; arrayfun 与 bsxfun 两个重要函数却鲜有人能够用好&#xff0c;今天针对这两个函数举例说明其威力。 Matlab arrayfun 概述 arrayfun 是 Matlab …

第五十天 第十一章:图论part01 图论理论基础 深搜理论基础 98. 所有可达路径 广搜理论基础

图论理论基础 了解邻接矩阵(*)&#xff0c;度&#xff0c;邻接表&#xff08;数组链表&#xff09;等 遍历顺序&#xff1a;深搜加广搜 深搜理论基础 dfs是可一个方向去搜&#xff0c;不到黄河不回头&#xff0c;直到遇到绝境了&#xff0c;搜不下去了&#xff0c…

力扣SQL 最后一个能进入巴士的人 自连接

Problem: 1204. 最后一个能进入巴士的人 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考题解 复杂度 时间复杂度: O ( ∗ ) O(*) O(∗)空间复杂度: O ( ∗ ) O(*) O(∗) Code select a.person_name from queue a,queue b where a.turn > b.turn -…

Java代理模式详细

Java代理模式详细 一、引言 代理模式&#xff08;Proxy Pattern&#xff09;是一种常用的设计模式&#xff0c;它为其他对象提供一种代理以控制对这个对象的访问。在Java中&#xff0c;代理模式可以分为静态代理和动态代理两种。本文将详细介绍代理模式的概念、实现方式以及应…

[极客大挑战 2019]PHP1

打开靶机 提示有备份&#xff0c;可以用工具扫描&#xff0c;我还没有配置好环境&#xff0c;搜了一下其他师傅的&#xff1a;备份的地址在这&#xff1a; /www.zip 下载后得到这几个文件&#xff1a; index.php就是上面打开的网页&#xff0c;其中有一段php代码&#xff1a;…