
简介这份软件工程实习记录文档面向本科软件工程专业学生尤其适合正在撰写实习周记、实习报告或毕业实习材料、需要真实过程素材参考的读者可用于对照修改与补全个人记录。压缩包内共1个doc文件约40KB篇幅集中便于直接查阅和摘录。文档按周记录实习过程从入司动员、分组开发到实现文件查找与排序、用HTML/CSS/JavaScript完成教师信息展示与添加再到Node.js结合Express与MySQL实现单页数据增删改查并涉及Redhat Linux环境、ARM开发板及网络服务器配置。记录中还穿插软件开发可行性分析、需求分析、概要设计、详细设计、编码与验收六阶段流程以及项目经理职责和开发岗位分工等知识点。目前已有2924人学习适合用来补充技术细节、梳理岗位认知并改写为符合学校要求的实习记录。1. 从「写代码」到「交付」一张软件工程实习全景图很多人对软件工程实习的想象是坐下就敲代码、一天交一个功能。翻完一份完整的软件工程实习记录会发现节奏完全不是这样五周时间里纯敲键盘写业务逻辑的比例低得惊人剩下的全花在读需求、搭环境、导数据、联调、排错和演示上。这份毕业实习记录的价值也在这里——它把「软件开发流程六步」「前后端与数据库怎么串起来」「服务器怎么部署」这三条线按时间摊开让你看到每一步真实的卡点长什么样。它适合两类人正在写实习记录、需要一份可对照的时序与知识点骨架的人以及复习软件工程、想把课上背的六步流程和技术栈对应到具体动作上的人。整份材料的技术重心其实只有四块流程与角色、桌面端与前端、数据链路、环境与部署。2. 开发流程六步可行性分析到验收每一步到底交什么几乎每个人都能背出可行性分析、需求分析、概要设计、详细设计、编码、项目验收这六步但被追问「概要设计和详细设计的边界在哪」「哪一步该出文档、哪一步该出可运行的东西」就卡住了。实习记录里那条最容易被忽略的判断是编码只占整个开发过程约百分之十五的时间剩下八成多分布在需求澄清、设计表达、环境准备和验收沟通上。把这个比例记住六步流程就不再是背下来的名词而是一条时间分配曲线。2.1 六个阶段的产出物与跳步的代价流程之所以是六步而不是三步是因为每一步都在降低后一步的不确定性。把它拆成「核心问题 典型产出 跳过的后果」三列复习时一眼就能对上号阶段核心问题典型产出跳过的后果可行性分析这件事值不值得做、技术上做不做得成可行性结论、技术选型初判做到一半发现依赖不成立返工需求分析用户到底要什么、边界在哪需求清单、功能点列表功能做出来没人用验收扯皮概要设计系统分几块、模块之间怎么调用架构图、模块划分、接口约定各写各的联调时接口对不上详细设计每个模块内部怎么实现类图、表结构、字段定义数据库建错后期改表牵一发动全身编码把设计翻译成可运行程序可运行代码、单元自测只有代码没有依据出问题无法回溯项目验收做出来的东西是否满足当初的需求演示、验收记录、部署包交付即结束问题全留在上线后这张表最值得盯的是「概要设计」和「详细设计」的分界前者回答「系统由哪些部分组成、部分之间怎么说话」后者回答「每一个部分内部用什么结构、数据怎么存」。实习记录里图书信息录入功能的建模落在概要设计与详细设计之间——把用户需求画成可讨论的模型让客户能直观看到功能长什么样再往下才落到表结构和字段。2.2 编码只占 15%时间被谁吃掉了从五周的记录往回倒推时间消耗大致是这样的环境搭建与依赖安装、数据准备与清洗、前后端联调、错误定位、功能演示与修改这五项加起来远超写业务代码本身。这不是效率低而是软件工程的常态。真正决定项目能不能按时交付的往往不是算法写得多漂亮而是环境能不能一次跑通、数据能不能正确落库、出错时能不能从日志里一眼看出原因。举个记录里的真实片段把一个写好的项目部署到服务器上配置完端口和地址后访问首页失败。直觉会去翻代码实际原因是配置的端口已经被别的进程占用换一个端口立刻正常。这类问题在流程里根本没有位置却实实在在吃掉半天时间。复习时如果把六步流程理解成「写代码的六个前置步骤」就会低估中间那些不产出代码的环节理解成「风险逐层收敛的六个关卡」才对得上那条 15% 的经验值。2.3 岗位地图开发员、架构师、项目经理各自盯什么实习记录里提到的一批 IT 岗位其实是流程六步在不同角色身上的投影。软件开发员盯编码与自测项目经理盯计划、组织、协调、控制这条线架构师盯概要设计和技术选型技术总监盯多条产品线的技术方向售前售后则站在需求与验收两端。把它们和流程对齐比孤立背岗位名称有用得多项目经理对「需求分析」和「项目验收」两端负主要责任中间所有延期都汇到他这里架构师对「概要设计」负主要责任决定模块怎么切、技术栈怎么选软件开发员对「详细设计」和「编码」负主要责任是唯一大量产出代码的岗位售前在需求分析之前介入售后在验收之后介入两头都不写代码但直接影响客户满意度。复习到这里可以记住一个判断一个岗位在六步流程里覆盖的段数越多越偏管理与决策覆盖段数越少但越深越偏技术执行。实习阶段被安排「扮演项目经理角色、共同探讨系统要实现哪些功能」本质是让你提前体验需求分析这一步的决策压力而不是真让你管人。2.4 先建模再写码模型是需求的简化实现记录里有一句判断很关键模型是用户需求的简化实现通过建模可以让客户更直观地了解软件功能的具体实现形式对开发人员有现实指导意义。这句话解释了为什么很多项目在需求确认后不直接开工而是先做一个能点、能看的模型。以图书信息录入功能为例建模阶段要确定的是「录入哪些字段、字段之间有没有约束、录入后在哪里看到结果」而不是「用哪个控件、走哪个接口」。前者的改动成本是一次讨论后者的改动成本是一次重构。很多团队翻车的地方在于把两者混在一起模型还没确认就开始写代码等客户说「这个字段我不需要」时代码已经写进三层结构里了。建模还有一个隐性收益它是团队内部对齐术语的场合。编号、姓名、课程名这类字段在需求文档里可能叫法各不相同画进模型之后必须统一成一个名字后面建表、写接口、做页面才有共同的锚点。3. 桌面端与前端Swing 文件查找排序与 HTML/CSS/JS 页面实习前两周的技术内容横跨桌面和网页两端表面上是两个不相干的任务实际练的是同一件事把「用户输入 → 处理 → 结果回显」这条链路走通。桌面端用 Swing 做文件查找与排序网页端用 HTML、CSS、JavaScript 做教师信息的表格展示与添加。这条链路看着简单但两个端各埋了一个典型坑桌面端把路径写死网页端把数据重复渲染。3.1 视图与主程序分包view 和 main 的职责边界桌面程序被拆成两个包一个放视图一个放主程序。视图包里做的是新建面板、添加组件和按钮、设置组件功能与相对位置主程序包里按运行逻辑写入口和调度。这种分法在小项目里显得啰嗦但它对应的是软件工程里最基本的一条原则——界面负责呈现和收集输入逻辑负责处理两者之间靠方法调用而不是互相引用。复习时可以这样检验自己是否真的理解分包如果把视图层整个换掉比如从 Swing 换成网页主程序里的业务逻辑要不要改答案是尽量不改。一旦发现换个界面就要动业务代码说明职责没分干净。实习记录里第二天写视图、第三天写主程序顺序上就是先定界面长什么样再定点击之后发生什么。3.2 固定路径写死查找功能的第一个真实缺陷查找功能的需求是在输入框输入文件名或商品名支持模糊查找把结果回显到页面。第一版做完能跑但只能从固定的地址查找。这个问题在演示时几乎必然被发现因为演示者一定会问「能不能查别的目录」。修改方式是把目录从常量抽成参数代码结构大致如下// 修改前目录写死在方法里换个位置就要改代码 // File root new File(D:/data/); // 修改后目录作为参数传入界面上的选择结果直接透传 public ListFile searchByName(File root, String keyword) { ListFile result new ArrayList(); if (root null || !root.exists()) { return result; // 目录不存在直接返回空避免空指针 } File[] files root.listFiles(); if (files null) { return result; // 无权限访问时 listFiles 返回 null必须判空 } for (File f : files) { if (f.isDirectory()) { result.addAll(searchByName(f, keyword)); // 递归子目录 } else if (f.getName().contains(keyword)) { result.add(f); // 模糊匹配用 contains等价于 SQL 的 like %keyword% } } return result; }这段代码有三个值得记住的参数与判断root从写死变成外部传入是「可配置」和「可测试」的分水岭listFiles()在目录无访问权限时返回null而不是空数组不判空会直接抛空指针模糊匹配用contains就够不需要正则因为需求只要求包含关系。递归遍历在目录层级深时有栈溢出风险实际项目里应改成队列做广度遍历但实习阶段用递归把逻辑讲清楚更重要。提示把「写死」当成一个检查项。凡是代码里出现绝对路径、固定 IP、固定端口、固定账号都标记出来它们在本地跑得通换台机器就翻车。3.3 冒泡排序按文件名排序能跑但别当最终方案排序功能的需求是把磁盘中现存的文件按文件名排序。记录里用的算法是冒泡排序比较依据是文件名。作为教学示例它没问题作为工程实现要补三个认知第一文件名是字符串字符串比较要用compareTo而不是减号比较结果的正负号才代表大小关系。第二String.compareTo按字符编码逐位比较中文文件名的排序结果既不是拼音序也不是笔画序只是一个稳定的字典序如果产品要求按拼音排必须额外引入排序键。第三冒泡排序的时间复杂度是 O(n²)文件数量上千之后切换目录就能感觉到卡顿实际应换成带比较器的排序。// 按文件名排序冒泡实现仅用于理解比较逻辑 public void sortByFileName(ListFile files) { for (int i 0; i files.size() - 1; i) { boolean swapped false; // 标记本轮是否发生交换 for (int j 0; j files.size() - 1 - i; j) { // 字符串比较必须用 compareTo 0 表示前者应排在后 if (files.get(j).getName().compareTo(files.get(j 1).getName()) 0) { File tmp files.get(j); files.set(j, files.get(j 1)); files.set(j 1, tmp); swapped true; } } if (!swapped) { break; // 本轮无交换说明已有序提前退出 } } }swapped标记是冒泡排序里最容易被省略又最该保留的一行它让最好情况本来就有序降到 O(n)。files.size() - 1 - i里的- i是因为每轮结束后末尾的 i 个元素已经就位不需要再比。理解这两处比背下整个算法更有用。3.4 三件套分工与「重复渲染」这个坑网页端的分工很清晰HTML 负责结构和布局CSS 负责外观JavaScript 负责动态效果。教师信息展示的做法是先把数据放在数组里再用表格渲染到页面。这一步只是静态数据真实项目里数据来自数据库读取后再回显这个「静态数组先跑通、再换成数据库」的路径是合理的因为它把「渲染逻辑对不对」和「数据来源通不通」两个问题拆开了。添加功能暴露的坑更典型新建三个输入框分别读取编号、姓名、课程名点击添加按钮后把信息显示到页面结果每次添加都会把之前的记录重复渲染一遍页面越点越长。原因在于渲染函数是「追加」而不是「重建」——每次添加都往容器里再插一遍全量数据。修法是在添加前先清空容器再整体重绘或者只增量插入新增的那一条。// 反例每次添加都追加全量数据页面出现重复行 // list.forEach(item table.appendChild(renderRow(item))); // 正例先清空再整体重绘保证页面与数据源一致 function renderTable(list) { const tbody document.querySelector(#teacherTable tbody); tbody.innerHTML ; // 关键一步清空旧节点 list.forEach(item { const tr document.createElement(tr); tr.innerHTML td${item.id}/tdtd${item.name}/tdtd${item.course}/td; tbody.appendChild(tr); }); }「数据变了就整体重绘」这个思路在数据量小的时候完全够用它保证页面永远是数据源的一次投影不会出现新旧混杂。数据量大时再考虑增量更新和虚拟列表但那是优化不是第一版要解决的问题。4. 从静态到动态Node.js Express MySQL 的数据链路第二周后半段的任务是把网页从「数组里的假数据」推到「数据库里的真数据」整条链路是浏览器发起请求 → Node.js 服务接收 → Express 路由分发 → 查询 MySQL → 结果转 JSON → 回显到页面。这条链路是后端入门最标准的骨架也是复习时最该在纸上默画一遍的部分因为它的每一段都有一个对应的排错入口。4.1 项目初始化npm init 之后得到了什么在空目录里执行npm init得到的是一个package.json它记录项目名、版本、入口文件和依赖列表。很多人把它当成一个可跳过的步骤实际上它是后面所有依赖管理的根装了 Express、装了 MySQL 驱动都会写进这里换台机器只要npm install就能还原环境。目录约定上入口文件放服务启动逻辑静态页面放公开目录路由和数据访问各自成文件这样后面加功能不用在一个文件里翻。4.2 请求响应层get 和 post 各管什么Express 的核心就两件事定义路由、处理请求与响应。get 用于获取数据参数挂在 URL 上服务端用req.query取post 用于提交数据参数在请求体里服务端用req.body取且必须先挂解析中间件否则取到的是 undefined。这条差异是新手最常见的翻车点用 post 提交表单却忘了挂解析器打印出来永远是空对象。const express require(express); const app express(); app.use(express.json()); // 解析 application/json 请求体 app.use(express.urlencoded({ extended: true })); // 解析表单提交 // get查询参数走 URL用 req.query 取 app.get(/api/books, async (req, res) { const keyword req.query.keyword || ; // 缺省为空串等价于查全部 const rows await queryBooks(keyword); res.json({ code: 0, data: rows }); // 统一返回结构前端好处理 }); // post提交数据走请求体用 req.body 取 app.post(/api/books, async (req, res) { const { name, author } req.body; if (!name) { return res.status(400).json({ code: 1, msg: 书名不能为空 }); // 参数校验前置 } await insertBook(name, author); res.json({ code: 0 }); }); app.listen(3000, () console.log(server on 3000)); // 端口被占用会直接报错express.json()和express.urlencoded()两行中间件决定了req.body有没有值res.json()会自动设置内容类型并序列化不要手动拼字符串app.listen的端口如果被别的进程占用启动阶段就会抛错这是好事——比运行到一半才失败容易定位。4.3 数据落库Excel 导入、JSON 转换与驱动选择数据从 Excel 进数据库中间要过三关第一关是建库建表字段类型要和 Excel 列的实际内容对得上编号用整型、名称用变长字符串第二关是导入把 Excel 另存为可解析的格式再批量插入逐条手输只适合几十行以内的演示数据第三关是读出来给前端Node 查 MySQL 拿到的是结果集对象需要转成 JSON 才能被页面消费。驱动层要装的是 MySQL 的 Node 辅助包连接时把主机、端口、用户名、密码、库名和字符集一起配上。字符集这一项最容易漏漏了之后单机测试一切正常一遇到中文就出问题。4.4 增删改查的本质按钮 → JS 函数 → SQL记录里有一句总结很到位对数据库的增删改查实际上是通过页面按钮的点击激活不同的 JavaScript 函数由函数去执行脚本从而执行不同的 SQL 语句。把这句话展开成一条可复现的路径页面上为每个操作绑定按钮按钮的点击事件指向一个函数函数里用fetch或表单提交把参数发到对应路由新增和修改走 post删除和查询走 get 或 post路由里拼 SQL查询用SELECT、新增用INSERT、修改用UPDATE、删除用DELETE执行完把影响行数或结果集返回前端据此刷新表格。这里最该警惕的是 SQL 拼接。用字符串拼where name 输入值 遇到带引号的内容就会报错更严重的是留下注入风险。参数化查询用占位符把值和语句分开是唯一正确的写法// 错误直接拼接用户输入引号和注入都挡不住 // const sql select * from book where name like %${keyword}%; // 正确占位符 参数数组驱动负责转义 const sql select id, name, author from book where name like ?; const rows await pool.query(sql, [%${keyword}%]); // 模糊匹配由通配符承担?的个数必须和参数数组长度一致多一个少一个都会报错通配符%要放在参数里而不是 SQL 里否则占位符会失效。4.5 中文乱码的三处源头页面、连接、库表中文信息录不进数据库是这条链路上出现频率最高的问题。原因只有一个链路上某一段的字符集和其他段不一致。页面用一套编码提交连接用另一套编码传输库表用第三套编码存储中间任何一段对不上中文就变成问号或乱码。记录里的处理是把数据库和页面的编码统一问题解决更稳的做法是全链路统一成支持四字节的字符集从建库、建表、连接串到页面声明保持一致。排查顺序建议固定成三步先看页面声明和提交编码再看连接配置里的字符集参数最后看库和表的默认字符集。三步都对齐还乱码再去看是不是导入数据时源文件的编码不对。这个顺序能覆盖绝大多数情况也能避免「只改页面编码就以为修好了」的误判。5. 易错点环境配置与部署排错的五条血泪经验第三周到第五周的内容从写代码转向了搭环境和部署这部分在实习记录里占的篇幅不大但对复习的人来说信息密度最高因为它记的全是「按教程做完却跑不起来」的场景。要理解这些坑先得有一张环境地图知道每一层各自管什么。5.1 环境地图Linux、IIS、Tomcat 与三层框架各管一段Linux 那一层管的是操作系统和编译工具链任务是能在命令行下编写、编译、运行一个最小程序并了解交叉编译的流程。服务器那一层分三类角色文件服务器把大容量磁盘空间提供给网上客户机使用接收数据处理和文件存取请求打印服务器接收来自客户机的打印任务通信服务器负责网与网之间的通信并提供多种接口。Web 容器那一层是 IIS 和 Tomcat 的天下IIS 跑在 Windows 上、以站点和虚拟目录为单位组织Tomcat 跑 Java Web 项目、以 webapps 目录为单位组织。框架那一层则是 Java Web 的三段式分工Struts 对应表示层Spring 对应业务逻辑层Hibernate 对应持久层。这样切的动机不是学术分类而是让分工不同的部门在同一套模式下写代码保证一个人写的程序另一个人能读懂同时把建表、映射这类重复劳动自动生成既保证可读性也降低成本。Spring 通过控制反转也叫依赖注入把对象的创建和依赖关系交给容器管理还引入面向切面编程处理事务这类横切逻辑Hibernate 在 JDBC 之上再封一层实现对象与关系映射不用手写 SQL 就能操作数据库。JSP 则是页面层的老技术在传统页面文件中加入 Java 程序片段和标签实现动态输出好处是对浏览器端要求低。5.2 交叉编译的最小闭环与它真正验证了什么在 Linux 环境下的第一个练习通常是新建目录写一个 hello.c 和一个 Makefile编译后下载到目标开发板上运行。这个练习的价值不在 hello 本身而在于它一次性验证了四件事工具链装对了、Makefile 写得对、编译产物能生成、产物能烧到板子上跑起来。任何一环断了后面的项目都无从谈起。复习时容易把「跑通了 hello」等同于「掌握了嵌入式开发」这是误判。它只证明了工具链闭环成立不证明你会写驱动、会调硬件接口。把它当成环境自检脚本更准确换一台机器、换一个开发板这套最小闭环要能重新跑一遍这才叫环境可控。5.3 五条易错点逐条对账第一条中文乱码只改页面编码就收工。易漏点在于乱码的成因分布在整个链路上页面只是最显眼的一段。为什么漏改页面编码最快见效改完看到部分正常就以为修好了。怎么补固定按「页面声明 → 连接参数 → 库表默认字符集」三步查三步全对齐再谈其他。第二条看到 500 错误就去改配置文件。记录里那个 Java 网站用 Tomcat 作服务器浏览器加载时报 500去服务器日志里找到一句「数据加载失败」一开始怀疑 Tomcat 配置改了很多遍都没用最后发现是驱动包和数据库版本不匹配导致的连接错误。为什么漏500 是服务端通用错误码它只说明「服务器处理时抛异常了」不说明异常在哪凭猜测改配置等于盲改。怎么补先去日志里找第一条带异常类名的堆栈从最内层的 caused by 往外读配置只在堆栈指向配置时才动。第三条部署后访问失败先怀疑代码。项目挪到 webapps 目录、配好端口和地址、启动服务器、访问首页失败最后发现是端口已被占用换端口后正常。为什么漏部署环节的失败原因大部分在环境而不在代码但人的注意力天然在刚写完的代码上。怎么补按「进程是否起来 → 端口是否在监听 → 地址和路径是否对 → 应用是否报错」四步排查端口占用这一类问题在第二步就能拦住。第四条本地 IIS 站点建好却打不开。记录里的处理是装系统、装 IIS、设置默认网站的主目录地址浏览器访问失败最后查到要设置 Internet 来宾账户的权限并且因为后续要做后台管理还要勾上修改权限另外只有在磁盘为 NTFS 格式时才能在对应系统版本下看到安全选项卡。为什么漏教程只写到「设主目录」权限这一步默认你会实际新手根本不知道去哪设。怎么补记住「站点打不开先看两件事——目录权限和默认文档」权限不够时错误页往往不报权限只报 401 或 403看到这两个码直接去查目录授权。第五条数据重复渲染当成样式问题。添加信息后页面越点越长第一反应往往是去看表格样式。为什么漏现象出现在页面上人就会往渲染层找。怎么补先判断是「数据源里有重复」还是「渲染时重复插入」打印一次数据源长度就能分清数据源正常就一定是渲染函数在追加而不是重建。注意这五条的共同点是「症状出现的位置」和「根因所在的位置」不在一层。排错的第一步永远是先确认症状属于哪一层再往下挖。6. 复习清单把五周内容压成一张对账表复习这类实习记录最省力的方式不是重读一遍流水账而是把它压成一张能自测的对账表逐行问自己「这一步的产出是什么、失败时先看哪里」。下面这张表可以直接抄下来当复习卡模块必须能说清的三个点失败时先看哪里流程六步每步产出物、概要设计与详细设计的分界、编码占比需求是否确认、设计是否有文档角色分工项目经理管两端、架构师管概要设计、开发员管编码责任是否落到具体人桌面端视图与逻辑分包、路径参数化、字符串比较是否有写死的绝对路径前端三件套结构/样式/行为分工、渲染前清空容器数据源长度是否正常数据链路路由分发、参数化查询、结果转 JSON请求体解析、占位符个数字符集页面、连接、库表三段对齐从页面往库表逐段排查部署端口监听、目录权限、驱动版本匹配日志第一条异常堆栈配套的查漏补缺方法有三条都是我自己反复验证过的。一是「默画链路」拿一张白纸从浏览器点击按钮开始一路画到数据库返回每一段标上可能的失败点画不出来的地方就是漏洞。二是「反向读日志」找一段报错堆栈从最内层往外读先定位异常类再看调用链最后才看自己写的业务代码。三是「环境复现」把项目在一台干净机器上从零跑一遍凡是需要「我记得当时装过什么」的步骤都补进文档因为这些步骤就是下次换机器时的坑。我踩得最狠的一次是排查一个页面打不开的问题盯着自己刚改的前端代码看了两个小时最后发现是服务压根没起来端口还被别的进程占着。从那以后我每次遇到「打不开、连不上、没反应」都强制走一遍「进程 → 端口 → 路径 → 日志」这四步不再一上来就怀疑自己写的代码。这份记录里五周的时间线、每类问题的排查路径和知识点分布都是现成的对着改一遍比从零回忆快得多需要的话可以拿去直接用。希望帮到你。本文还有配套的精品资源点击获取