ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

软件工程第一次作业-前后端分离计算器

软件工程第一次作业-前后端分离计算器 软件工程第一次作业——前后端分离计算器系统课程与作业信息课程名称软件工程作业名称第一次作业——前后端分离计算器系统姓名林昊旻学号832401116作业目标实现一套前后端分离计算器完成安全表达式计算、异常处理、历史记录持久化、指定记录删除以及公网部署。参考资料Python 官方文档、SQLite 官方文档、MDN Fetch API 文档、GitHub Pages 文档、PythonAnywhere 帮助文档。目录课程与作业信息一、作业简介二、项目地址与代码规范三、PSP 表格四、需求分析4.1 功能需求4.2 前后端分离要求五、整体系统设计5.1 系统架构5.2 功能结构六、前端设计与实现七、后端设计与表达式解析八、API 接口设计九、数据库设计与历史模块十、异常处理十一、测试与成品展示11.1 加法11.2 减法11.3 乘法11.4 除法11.5 小数运算11.6 运算符优先级11.7 括号运算11.8 平方根扩展11.9 次方扩展11.10 除零异常11.11 一元负号11.12 非法表达式11.13 GitHub 双仓库十二、部署过程12.1 后端部署到 PythonAnywhere12.2 前端部署到 GitHub Pages十三、遇到的问题与解决方案13.1 混淆 GitHub Project 与 Repository13.2 GitHub Pages 无法运行 Python13.3 公网前端不能访问本机地址13.4 后端更新后没有自动生效13.5 首次发布需要等待构建十四、个人收获与体会十五、总结一、作业简介本次作业要求开发一套前后端分离的计算器系统。前端负责表达式输入、按钮交互、结果展示、历史记录展示和删除请求后端负责输入校验、表达式解析、数学计算、异常处理与数据库操作。前后端通过 HTTPS 和 JSON API 通信。本项目实现了加、减、乘、除、小数、括号、运算符优先级和一元正负号支持非法表达式与除零异常处理。每次成功计算都会写入 SQLite 数据库用户可以查询和删除指定历史记录。在基础要求之外还实现了百分号、平方根和次方运算。二、项目地址与代码规范前端仓库832401116_calculator_frontend后端仓库832401116_calculator_backend前端代码规范frontend/codestyle.md后端代码规范backend/codestyle.md前端公网地址在线计算器后端历史接口GET /api/history三、PSP 表格以下为本次开发的时间记录单位为分钟。PSP 阶段具体工作预计耗时实际耗时Planning需求分析3030Planning技术选型与系统设计4040Development前端页面开发12090Development后端接口开发120100Development表达式解析模块120120DevelopmentSQLite 历史模块6055Development根号、次方扩展4047Test前后端联调6061Test功能与异常测试6057DeploymentGitHub 与公网部署9090Reporting截图整理与博客撰写120150合计860840四、需求分析4.1 功能需求支持加法、减法、乘法和除法。支持小数、复合表达式、运算符优先级和括号。支持一元正负号例如-58和3*-2。能识别非法表达式并处理除数为零等异常。每次成功计算都保存表达式、结果和时间。前端能够从后端数据库读取并展示历史记录。用户能够按记录 ID 删除指定历史记录。扩展支持百分号、平方根和次方运算。4.2 前后端分离要求本项目的前端只负责收集表达式并展示结果不在浏览器中计算最终答案。用户点击等号后前端把表达式发送给后端后端完成校验、解析、计算和数据库写入再将结果返回前端。停止后端后页面仍可显示并输入表达式但无法得到新的有效结果由此可以验证核心计算位于后端。五、整体系统设计5.1 系统架构系统由浏览器前端、Python 后端和 SQLite 数据库组成用户浏览器 ↓ HTTPS GitHub Pages 前端 ↓ HTTPS JSON PythonAnywhere 后端 ↓ SQL SQLite 数据库前端部署于 GitHub Pages负责静态页面、按钮交互和结果展示后端部署于 PythonAnywhere负责表达式解析、计算、异常处理和数据库操作SQLite 负责持久保存计算记录。5.2 功能结构计算器系统 ├── 前端模块 │ ├── 表达式输入 │ ├── 结果展示 │ ├── 历史展示 │ └── 删除请求 ├── 后端模块 │ ├── 输入校验 │ ├── 表达式解析 │ ├── 数学计算 │ └── 异常处理 └── 数据库模块 ├── 保存历史 ├── 查询历史 └── 删除历史六、前端设计与实现前端使用 HTML5、CSS3 和原生 JavaScript 实现。HTML 定义页面结构CSS 负责响应式计算器布局JavaScript 负责按钮交互、表达式输入、Fetch 请求及后端响应展示。前端计算流程如下用户点击按钮 → 前端组成表达式 → 点击等号 → POST 表达式到后端 → 接收后端 JSON → 展示结果 → 重新查询历史记录关键请求代码如下constresponseawaitfetch(API_BASE/api/calculate,{method:POST,headers:{Content-Type:application/json},body:JSON.stringify({expression})});constdataawaitresponse.json();resultEl.textContentdata.result;请求体只包含用户输入的表达式最终结果由后端计算并返回因此没有出现“前端算完后只把结果交给后端保存”的错误实现。七、后端设计与表达式解析后端使用 Python 标准库实现不依赖第三方 Web 框架。本地服务使用ThreadingHTTPServer公网部署使用 WSGI 入口历史记录由sqlite3持久化。为了避免执行任意代码的安全问题项目没有使用eval、exec或等价方法而是自行实现递归下降解析器。其主要层次为expression处理 、- term处理 *、/ unary处理一元 、- power处理 ^ primary处理数字、括号和 sqrt(...)解析层次直接体现数学优先级。例如_expression()先调用_term()因此乘除法会先于加减法计算遇到括号时解析器递归解析括号内部表达式。后端计算流程如下接收表达式 → 检查类型、长度和字符 → 按优先级解析 → 执行计算 → 成功结果写入 SQLite → 返回标准 JSON八、API 接口设计请求方法接口作用成功状态码POST/api/calculate计算表达式并保存历史201GET/api/history查询全部历史记录200DELETE/api/history/{id}按 ID 删除指定记录200计算请求示例{expression:(12)*3}成功响应示例{success:true,expression:(12)*3,result:9}错误响应示例{success:false,message:除数不能为零}后端还配置了 CORS 响应头使部署在 GitHub Pages 域名下的前端可以访问 PythonAnywhere API。九、数据库设计与历史模块项目使用 SQLite 保存计算历史。SQLite 无需单独启动数据库服务适合本次单用户、数据规模较小的课程项目。字段类型与约束含义idINTEGER PRIMARY KEY AUTOINCREMENT记录唯一编号expressionTEXT NOT NULL原始表达式resultTEXT NOT NULL计算结果created_atTEXT NOT NULL计算时间只有成功计算才会写入数据库。前端打开或刷新时调用GET /api/history所以历史记录来自后端 SQLite而不是浏览器变量或 LocalStorage。删除时前端根据记录 ID 调用DELETE /api/history/{id}删除成功后再次查询后端数据并更新页面。十、异常处理后端对以下情况进行了处理表达式为空表达式超过长度限制包含非法字符括号不匹配表达式格式不完整除数为零负数开平方根次方结果无效或结果超出范围请求接口不存在。出现异常时后端返回success: false和具体错误信息前端负责把后端消息显示给用户失败记录不会写入数据库。十一、测试与成品展示11.1 加法图 1公网计算器主界面与加法测试。浏览器地址栏显示 GitHub Pages 公网地址页面显示“后端已连接”输入50020后得到520右侧出现数据库历史记录证明前后端公网联调成功。11.2 减法图 2减法测试。输入260-10后端返回250计算结果正确。11.3 乘法图 3乘法测试。输入6×7后端返回42同时新增一条历史记录。11.4 除法图 4除法测试。输入81÷9前端传输/后端计算并返回9。11.5 小数运算图 5小数运算测试。输入1.52.25后端返回3.75说明解析器能够正确识别小数。11.6 运算符优先级图 6运算符优先级测试。输入23×9结果为29说明后端先计算乘法再计算加法。11.7 括号运算图 7括号运算测试。输入(23)×9结果为45说明括号可以改变默认运算顺序。11.8 平方根扩展图 8平方根扩展功能。输入√81后端将其解析为sqrt(81)并返回9。11.9 次方扩展图 9次方扩展功能。输入2^10后端返回1024。11.10 除零异常图 10除零异常测试。输入1÷0后页面显示“错误”和“除数不能为零”且该失败表达式没有写入成功历史。11.11 一元负号图 11一元负号测试。输入-58后端返回3说明解析器能够区分减法运算符和一元负号。11.12 非法表达式图 12非法表达式测试。输入格式错误的表达式后后端拒绝计算并返回错误信息前端将其展示给用户。11.13 GitHub 双仓库图 15后端 GitHub 仓库。仓库中包含README.md、codestyle.md、后端入口、表达式解析和测试文件。图 16前端 GitHub 仓库。仓库中包含index.html、README.md和codestyle.md并已通过 GitHub Pages 发布。十二、部署过程12.1 后端部署到 PythonAnywhere在 PythonAnywhere 的 Bash 控制台克隆后端仓库创建 Manual configuration 类型的 Web 应用选择 Python 3.13在 WSGI 配置中加入项目路径并导入应用保存配置并点击 Reload访问/api/history确认能够返回 JSON。WSGI 配置如下importsys project_path/home/sorreey/backend_repoifproject_pathnotinsys.path:sys.path.insert(0,project_path)fromappimportapplicationSQLite 文件位于后端项目目录中PythonAnywhere 负责持续运行 WSGI 应用并接收公网请求。12.2 前端部署到 GitHub Pages将前端文件提交到独立 GitHub 仓库把API_BASE修改为 PythonAnywhere 公网地址在仓库Settings → Pages中选择Deploy from a branch选择main分支和/ (root)目录保存并等待 GitHub Pages 完成首次构建。前端中的公网后端地址为constAPI_BASEhttps://sorreey.pythonanywhere.com;部署后的完整访问流程为同学访问 GitHub Pages → 浏览器加载前端文件 → 前端向 PythonAnywhere 发起 HTTPS 请求 → 后端计算并访问 SQLite → 后端返回 JSON → 前端显示结果和历史记录十三、遇到的问题与解决方案13.1 混淆 GitHub Project 与 Repository开始时误把 GitHub Project 当作代码仓库。查明两者用途后重新建立前端和后端两个独立 Repository分别保存两部分源代码。13.2 GitHub Pages 无法运行 PythonGitHub Pages 只能托管 HTML、CSS 和 JavaScript 等静态文件无法执行 Python 后端。因此将前端部署到 GitHub Pages将后端部署到 PythonAnywhere。13.3 公网前端不能访问本机地址本地开发时后端地址为127.0.0.1:8000它只指向访问者自己的电脑。部署时将前端的API_BASE修改为 PythonAnywhere 的 HTTPS 公网地址完成跨域联调。13.4 后端更新后没有自动生效GitHub 仓库更新不会自动替换 PythonAnywhere 中正在运行的代码。后端修改后需要在服务器执行git pull并在 Web 页面点击 Reload使服务重新加载最新代码。13.5 首次发布需要等待构建GitHub Pages 保存配置后不会立即可访问需要等待自动构建。通过访问公网地址并检查“后端已连接”状态最终确认部署成功。十四、个人收获与体会通过本次作业我理解了前后端分离并不是简单地把文件放到两个文件夹而是让前端和后端具有明确职责并通过 HTTP API 独立通信。前端负责交互与展示后端负责可信的核心计算、异常处理和数据库操作。开发过程中我学习了递归下降表达式解析、运算符优先级、Fetch 请求、JSON 数据传输、CORS、SQLite 持久化、GitHub 双仓库管理、GitHub Pages 静态部署以及 PythonAnywhere 的 WSGI 配置。我也认识到本地运行成功并不代表公网环境一定可用部署时还需要检查接口地址、HTTPS、跨域响应和服务器入口。目前项目已经满足基础计算、复合表达式、异常处理、历史持久化和单条删除等要求。未来可以继续增加历史搜索与分页、主题切换、键盘帮助和不同用户的独立历史记录。十五、总结本项目完成了一个可公网访问的前后端分离计算器。前端部署于 GitHub Pages后端部署于 PythonAnywhere双方通过 HTTPS 和 JSON API 通信后端使用安全解析器完成计算并通过 SQLite 持久化历史记录。经过基础运算、复合表达式、异常处理、历史持久化和删除测试系统能够稳定完成本次作业要求。
返回列表