From 8b4090ea35525455552d57eb409c3bf191a3dbf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E4=BD=B3=E6=95=8F?= <878083710@qq.com> Date: Mon, 30 Mar 2026 10:56:44 +0800 Subject: [PATCH 1/4] 1 --- ...30\344\270\255\351\227\264\344\273\266.md" | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 "\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" diff --git "a/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" "b/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" new file mode 100644 index 0000000..aa244ab --- /dev/null +++ "b/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" @@ -0,0 +1,84 @@ +# 简答题 +## 第一题:什么是中间件?它在Express中起什么作用? +中间件 = 请求处理管道 + +所有功能(解析、日志、鉴权、跨域、错误处理)都是靠中间件实现的 + +路由本身,本质上也是一种 “匹配路径后才执行” 的中间件 +## 第二题:中间件函数中的next()函数有什么作用?如果不调用会怎样? +next() = 放行,继续执行下一个中间件 / 路由 + +不调用 next() 且不返回响应 = 请求挂起、前端超时 +## 第三题:应用级中间件和路由级中间件有什么区别? +应用级中间件:全局通用,绑在 app + +路由级中间件:局部专用,绑在 router,只对某一组接口生效 +## 第四题:错误处理中间件和普通中间件有什么区别? +普通中间件:3 个参数,处理正常请求 + +错误处理中间件:4 个参数,专门捕获 next (err) 抛出的错误 +## 第五题:如何在中间件中传递数据给后面的处理函数? +在中间件中将数据挂载到 req 对象上,后面的中间件和路由处理函数就可以通过 req 访问到这些数据。 +# 操作题 +## 第一题:IP限制中间件:创建一个中间件,记录请求IP并限制某些IP访问。 +``` +// 黑名单IP +const blackIP = ['127.0.0.1'] + +// IP限制中间件 +const ipFilter = (req, res, next) => { + const ip = req.ip + console.log('请求IP:', ip) + + if (blackIP.includes(ip)) { + return res.send('禁止访问') + } + next() +} + +// 使用 +app.use(ipFilter) +``` +## 第二题:请求超时中间件:创建一个中间件,如果请求超过指定时间未响应,返回超时错误。 +``` +// 请求超时中间件(5秒超时) +const timeout = (req, res, next) => { + const timer = setTimeout(() => { + res.status(504).send('请求超时') + }, 5000) + + // 正常响应时清除定时器 + const end = res.end + res.end = (...args) => { + clearTimeout(timer) + end.apply(res, args) + } + + next() +} + +// 使用 +app.use(timeout) +``` +## 第三题:请求体验证:创建一个中间件,验证请求体中的必填字段。 +``` +// 校验 body 必须有 name 和 age +const validateBody = (req, res, next) => { + const { name, age } = req.body + + if (!name || !age) { + return res.status(400).send('缺少必填字段:name 或 age') + } + + next() +} + +// 使用 +app.use(express.json()) // 必须先解析body +app.post('/user', validateBody, (req, res) => { + res.send('验证通过') +}) +``` +## 第四题:统一错误响应:改造错误处理中间件,统一返回格式。 + +## 第五题:中间件组合:使用多个中间件实现一个完整的请求处理流程:日志 → 认证 → 业务处理。 \ No newline at end of file -- Gitee From 3abfb9cf869f932ab1e5ecdf32633b271229d09d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E4=BD=B3=E6=95=8F?= <878083710@qq.com> Date: Tue, 31 Mar 2026 14:20:44 +0800 Subject: [PATCH 2/4] 1 --- ...30\344\270\255\351\227\264\344\273\266.md" | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git "a/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" "b/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" index aa244ab..8b9072e 100644 --- "a/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" +++ "b/\345\274\240\344\275\263\346\225\217/20260330\344\270\255\351\227\264\344\273\266.md" @@ -80,5 +80,29 @@ app.post('/user', validateBody, (req, res) => { }) ``` ## 第四题:统一错误响应:改造错误处理中间件,统一返回格式。 +``` +import lombok.Data; + +@Data +public class R { + private int code; + private String msg; + private Object data; -## 第五题:中间件组合:使用多个中间件实现一个完整的请求处理流程:日志 → 认证 → 业务处理。 \ No newline at end of file + public static R ok(Object data) { + R r = new R(); + r.code = 200; + r.msg = "success"; + r.data = data; + return r; + } + + public static R fail(int code, String msg) { + R r = new R(); + r.code = code; + r.msg = msg; + r.data = null; + return r; + } +} +``` \ No newline at end of file -- Gitee From c8b7d19e7ef9486042510521ca5d59ffaab2b6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E4=BD=B3=E6=95=8F?= <878083710@qq.com> Date: Thu, 2 Apr 2026 11:02:34 +0800 Subject: [PATCH 3/4] 1 --- ...25\346\223\216\347\254\224\350\256\260.md" | 48 +++++ ...27\345\274\225\346\223\216\351\242\230.md" | 179 ++++++++++++++++++ 2 files changed, 227 insertions(+) create mode 100644 "\345\274\240\344\275\263\346\225\217/20260401\346\250\241\345\235\227\345\274\225\346\223\216\347\254\224\350\256\260.md" create mode 100644 "\345\274\240\344\275\263\346\225\217/20260402\346\250\241\345\235\227\345\274\225\346\223\216\351\242\230.md" diff --git "a/\345\274\240\344\275\263\346\225\217/20260401\346\250\241\345\235\227\345\274\225\346\223\216\347\254\224\350\256\260.md" "b/\345\274\240\344\275\263\346\225\217/20260401\346\250\241\345\235\227\345\274\225\346\223\216\347\254\224\350\256\260.md" new file mode 100644 index 0000000..09ab1df --- /dev/null +++ "b/\345\274\240\344\275\263\346\225\217/20260401\346\250\241\345\235\227\345\274\225\346\223\216\347\254\224\350\256\260.md" @@ -0,0 +1,48 @@ +# ejs的笔记 +## 第一步:安装 +npm install ejs express +## 第二步:express配置ejs(页面放在view文件夹里,后缀.ejs) +``` +const express = require('express') +const app = express() + +// 1. 设置模板引擎为 ejs +app.set('view engine', 'ejs') +// 2. 设置模板文件存放目录(默认 views 文件夹) +app.set('views', './views') + +app.listen(3000, ()=>{ + console.log('服务启动') +}) +``` +标签 作用 +<%= %> 输出变量,转义 HTML(安全) +<%- %> 输出 HTML,不转义(富文本用) +<% %> 写 JS 代码(if/for/ 变量,不输出) +<%# %> 注释(不会编译到页面) +## 小案例 +``` +<%- include('header', {title:'用户页'}) %> + +

欢迎 <%= username %>

+ +<% if(vip){ %> +

你是VIP会员

+<% } %> + + +``` +### js端 +``` +app.get('/user', (req,res)=>{ + res.render('index',{ + username: '李四', + vip: true, + news: ['公告1','公告2','公告3'] + }) +}) +``` \ No newline at end of file diff --git "a/\345\274\240\344\275\263\346\225\217/20260402\346\250\241\345\235\227\345\274\225\346\223\216\351\242\230.md" "b/\345\274\240\344\275\263\346\225\217/20260402\346\250\241\345\235\227\345\274\225\346\223\216\351\242\230.md" new file mode 100644 index 0000000..30a9069 --- /dev/null +++ "b/\345\274\240\344\275\263\346\225\217/20260402\346\250\241\345\235\227\345\274\225\346\223\216\351\242\230.md" @@ -0,0 +1,179 @@ +# 简答题 +## 第一题:什么是模板引擎?它在Web开发中起什么作用? +模板引擎就是后端专用的 “HTML 自动拼装机器”: +拿模板 + 拿数据 → 自动生成完整动态网页,发给浏览器展示。 +## 第二题:EJS中<%= %>和<% %>有什么区别? +``` +<% + let name = "张三"; + if(age >= 18){ + msg = "成年人"; + } +%> + +

用户名:<%= name %>

+

状态:<%= msg %>

+``` +写逻辑、循环判断 → 用 <% %> +展示文字变量到页面 → 用 <%= %> +## 第三题:什么是MVC架构?每个部分分别负责什么? +MVC是一种项目分层架构思想,把代码拆分成三部分: + +M (模型) + V (视图) + C (控制器) +## 第四题:Express中如何配置和使用模板引擎? +先安装:npm install express ejs + +``` +const express = require('express') +const app = express() + +// ① 设置模板引擎为 ejs +app.set('view engine', 'ejs') +// ② 设置模板文件存放目录(默认就是 views,写上更清晰) +app.set('views', './views') +``` +js +``` +// 渲染 index.ejs,并且传数据给模板 +app.get('/', (req, res) => { + res.render('index', { + name: '小明', + age: 18 + }) +}) +``` +ejs +``` +

姓名:<%= name %>

+

年龄:<%= age %>

+``` +## 第五题:静态资源和模板文件有什么区别? +在express里用: +``` +app.use(express.static('public')) +``` +静态资源:直接发给浏览器,不改不动 +模板文件:后端加工填数据,动态生成网页 + +# 操作题 +## 第一题:博客列表页:使用EJS创建博客文章列表页,显示文章标题、作者、发布日期。 +先安装express和ejs:npm install express ejs +app.js +``` +const express = require('express') +const app = express() + +// 配置EJS模板引擎 +app.set('view engine', 'ejs') +app.set('views', './views') + +// 模拟博客数据(后端假数据) +const blogData = [ + { + title: 'Node.js入门教程', + author: '张三', + date: '2026-04-01' + }, + { + title: 'EJS模板引擎使用技巧', + author: '李四', + date: '2026-04-02' + }, + { + title: 'MVC架构详解', + author: '王五', + date: '2026-04-03' + } +] + +// 博客列表路由 +app.get('/blog', (req, res) => { + // 把博客数据传给EJS模板 + res.render('blogList', { list: blogData }) +}) + +// 启动服务 +app.listen(3000, () => { + console.log('服务器启动:http://localhost:3000/blog') +}) +``` +view/blogs.ejs +``` + + + + + 博客列表页 + + + +

博客文章列表

+ + + +``` +终端执行:node app.js + +浏览器打开:http://localhost:3000/blog +分页功能:为列表页添加分页,显示页码和上下页按钮。 + +## 第二题:文章详情页:创建文章详情页,点击标题可以查看文章内容。 +``` +// 引入 Node.js 内置模块 +const http = require('http'); +const url = require('url'); + +// 文章数据 +const articles = [ + { id: 1, title: "前端学习", content: "HTML + CSS + JS 是基础" }, + { id: 2, title: "JS 基础", content: "变量、函数、循环很重要" }, + { id: 3, title: "CSS 布局", content: "Flex 和 Grid 最好用" } +]; + +// 创建服务器 +const server = http.createServer((req, res) => { + const pathObj = url.parse(req.url, true); + const id = pathObj.query.id; + + // 文章列表页 + if (!id) { + res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' }); + let html = '

文章列表

'; + articles.forEach(art => { + html += `

${art.title}

`; + }); + res.end(html); + } + // 文章详情页 + else { + const art = articles.find(item => item.id == id); + res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' }); + if (art) { + res.end(` +

${art.title}

+

${art.content}

+ 返回 + `); + } else { + res.end('找不到文章'); + } + } +}); + +// 启动服务 +server.listen(3000, () => { + console.log('服务已启动:http://localhost:3000'); +}); +``` \ No newline at end of file -- Gitee From 202139fbe2901d90c34f0bc7d45b5633f9e1c2a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E4=BD=B3=E6=95=8F?= <878083710@qq.com> Date: Mon, 6 Apr 2026 20:15:35 +0800 Subject: [PATCH 4/4] 1 --- ...23\346\236\204\347\254\224\350\256\260.md" | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 "\345\274\240\344\275\263\346\225\217/20260403-mvc\347\273\223\346\236\204\347\254\224\350\256\260.md" diff --git "a/\345\274\240\344\275\263\346\225\217/20260403-mvc\347\273\223\346\236\204\347\254\224\350\256\260.md" "b/\345\274\240\344\275\263\346\225\217/20260403-mvc\347\273\223\346\236\204\347\254\224\350\256\260.md" new file mode 100644 index 0000000..23b26d0 --- /dev/null +++ "b/\345\274\240\344\275\263\346\225\217/20260403-mvc\347\273\223\346\236\204\347\254\224\350\256\260.md" @@ -0,0 +1,20 @@ +MVC 核心架构(三驾马车) +MVC 是一种软件设计模式,核心目的是“分离关注点”,让代码更易维护、测试和复用。 +1. Model (模型):负责数据与业务逻辑。 +◦ 它不仅存储数据,还包含数据的验证规则、业务逻辑计算、数据库交互等。 +◦ 核心职责:处理数据,不关心如何展示。 +◦ 例子:一个User模型,包含username属性,并有validate()验证方法。 +2. View (视图):负责用户界面展示。 +◦ 它是用户看到的东西,负责将模型数据呈现给用户,并接收用户的输入操作。 +◦ 核心职责:呈现数据,不关心业务逻辑。 +◦ 例子:一个HTML页面、一个移动端界面,展示用户信息。 +3. Controller (控制器):负责流程控制与调度。 +◦ 它是连接Model和View的桥梁。接收用户请求,调用Model处理业务,再选择合适的View返回结果。 +◦ 核心职责:协调工作,接收输入,调度处理。 +◦ 例子:接收用户登录请求,调用User模型验证,成功则跳转到主页,失败则返回登录页。 +完整交互流程(一次请求) +1. 用户操作:用户在 View 上触发动作(如点击登录按钮)。 +2. 控制器介入:Controller 接收到请求,调用 Model 进行处理。 +3. 模型处理:Model 执行业务逻辑,操作数据(如查询数据库),并返回处理结果。 +4. 视图渲染:Controller 根据 Model 的结果,选择并渲染对应的 View。 +5. 用户呈现:最终的 View 展示给用户。 -- Gitee