简介:《软件工程实习记录》面向高校软件工程、计算机相关专业准备实习报告或毕业材料的学生,也可供刚进入项目组的开发者梳理开发流程。记录以周记形式还原实习全过程,从可行性分析、需求分析、概要设计、详细设计、编码到项目验收逐一展开,并穿插项目经理职责、开发岗位分工及前端、后端、数据库等技术栈说明。内容还涉及 Eclipse Swing 界面设计、文件查找与排序、HTML/CSS/JavaScript 页面、Node.js 与 MySQL 增删改查、Linux 开发环境等实践环节,便于读者对照修改自己的实习记录,补充流程认知与项目细节。资源包共 1 个 doc 文件,约 40KB,篇幅紧凑、便于查阅;目前已有 2924 人学习,适合作为实习记录撰写和软件开发入门复盘的参考。
1. 从一份 2018 年的软件工程实习记录里,整理出一套可复现的环境清单
这份记录从 2018 年 8 月 27 日写到 9 月 28 日,五周,每天一段。很多人把它当周记模板,抄完交给学校;我关注的却是里面那一串环境:Eclipse 里拖出来的 Swing 面板、cmd 里敲的 npm init、装到一半失败的 MySQL、只肯认 89 端口的 Tomcat、还有那台 NTFS 格式的 IIS 机器。这份软件工程实习记录写到了每一次实际遇到的问题:查找功能只能扫固定目录、数据库安装时漏选一个选项、端口被占导致页面打不开。如果你正在准备毕业实习材料,或者想把这套 Java + Node.js + MySQL + Tomcat 的组合在本机重新搭建一遍,下面这套顺序、参数和排查方法可以直接照抄。
2. JDK 与 Eclipse:把 Swing 查找面板在本机编译出来
记录里 8 月 28 日和 8 月 30 日两天做的是同一件事:打开 Eclipse,新建com.shixi.viwe包,用 Swing 拖组件做查找面板和排序面板。这段看着最没技术含量,实际上最容易在第 3 天放弃——难的地方通常不在 Swing:JDK 装完java能跑、javac找不到,或者 Eclipse 启动就弹“找不到 JVM”。先把启动前的问题处理掉,再谈拖组件。
2.1 JDK 版本与 JAVA_HOME 的三处路径
2018 年那批教学和办公机器上跑的 Eclipse 多是 4.x,配套 JDK 8 是有原因的:JDK 9 之后模块化把rt.jar拆了,老插件和一堆教学用的第三方 jar 会直接报类找不到。我自己复现这类环境时,会老实装 JDK 8,不追新的原因就在这里。Swing 是 JDK 自带,不需要额外下任何包,比后来的 JavaFX 省心。
# 解压到 /opt,目录名换成你实际解出来的那个,别照抄 sudo tar -zxvf jdk-8-linux-x64.tar.gz -C /opt/ # 三处都写对才有用:根目录、bin、lib 下的两个 jar export JAVA_HOME=/opt/jdk1.8.0 export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$JAVA_HOME/bin:$PATH java -version javac -version这段里最容易写错的是JAVA_HOME的层级。它必须指向 JDK 根目录,不能带/bin,也不能带/jre;PATH才指向bin。两个命令的输出版本号必须一致,一个 1.8 一个 11,说明机器上还有另一份 JRE 抢在前面。Windows 上同理,在系统环境变量里改,改完要新开一个 cmd 窗口才生效,旧窗口读的还是老值。
| 变量名 | 应该指向 | 写错之后的表现 |
|---|---|---|
| JAVA_HOME | JDK 根目录 | Eclipse 提示找不到 JVM,或 Tomcat 起不来 |
| PATH | %JAVA_HOME%\bin | javac不是内部或外部命令 |
| CLASSPATH | lib下的dt.jar、tools.jar | 编译期报找不到类,运行期报 NoClassDefFoundError |
2.2 工作空间与包结构:com.shixi.viwe 这个名字别乱改
记录里包名拼成了viwe,是view的笔误,但它出现在两天的日记里,说明整个项目都是按这个拼写走的。自己重写没问题,改之前先想清楚:包名和目录结构是绑死的,com.shixi.viwe对应src/com/shixi/viwe/,改了包声明却没改目录,Eclipse 只会给你一片红。工作空间目录也别放中文路径和带空格的路径,这类问题排查起来毫无线索。
package com.shixi.viwe; import javax.swing.*; import java.awt.*; public class FileSearchPanel extends JPanel { // 输入框:文件名或商品名,支持模糊匹配 private final JTextField keywordField = new JTextField(20); // 查找按钮,点击后触发扫描 private final JButton searchButton = new JButton("查找"); // 结果区,用列表回显 private final DefaultListModel<String> resultModel = new DefaultListModel<>(); public FileSearchPanel() { setLayout(new BorderLayout()); JPanel top = new JPanel(); top.add(keywordField); top.add(searchButton); add(top, BorderLayout.NORTH); add(new JScrollPane(new JList<>(resultModel)), BorderLayout.CENTER); } }面板本身没什么玄学,重点是组件要设成成员变量而不是局部变量,否则按钮的监听器里拿不到输入框的值。DefaultListModel单独抽出来也是这个道理:结果集变了只动 model,界面自动刷新,不用手动repaint。布局用BorderLayout把输入区钉在上面、结果区撑满中间,比到处写setBounds稳得多,换个分辨率也不会散架。
2.3 从写死目录到可选目录:一次真实的返工
8 月 29 日那段写得很实在:功能做完了,发现只能从固定地址查找,提了疑问才改对。这是新手最容易出现的问题——路径写死在方法体里,测试数据一换就废。我一般会把根目录抽成构造参数,默认值只留一处,改的时候不至于全局搜索。
// 把写死的 "D:/data" 换成构造参数,默认值集中在一处 private final java.io.File rootDir; public FileSearchPanel(java.io.File rootDir) { this.rootDir = rootDir; }第二天补的排序功能,记录里写的是冒泡排序、按文件名排。冒泡本身没问题,教学项目里够用,但中文文件名直接String.compareTo排出来是乱序的——它按 Unicode 码点比,不按拼音比。要按中文习惯排,得换Collator。
import java.text.Collator; import java.util.*; // 中文文件名必须用 Collator,否则排序结果是乱的 Collator cn = Collator.getInstance(Locale.CHINA); Arrays.sort(files, (a, b) -> cn.compare(a.getName(), b.getName()));数据量小的目录,冒泡和Arrays.sort你感觉不出差别;一旦目录里上万个子文件,冒泡的 O(n²) 会让界面卡住好几秒。我的做法是排序放到后台线程,界面先出结果再刷新,至少不会被人当成程序崩了。
2.4 入口类与打包:main 放在 com.shixi.main
记录里 8 月 29 日另建了com.shixi.main包写主程序,这个分包习惯值得保留:界面归界面,启动逻辑归启动逻辑,后面要改成别的入口不用动视图层。Eclipse 里右键Run As → Java Application能跑,只说明工作空间里没问题;交付给别人时要打成可执行 jar,Main-Class必须带完整包名,漏了包名就是no main manifest attribute。
# 把编译产物打成可执行 jar,Main-Class 必须写全限定名 jar cfe FileTool.jar com.shixi.main.Main -C out . # 验证:双击或命令行运行都应该出界面 java -jar FileTool.jar-C out .的意思是切到out目录再打包当前层内容,这样 jar 里不会多出一层out/。如果运行时报Could not find or load main class,八成是包名和目录层级对不上,回2.2检查package声明。
3. Node.js 与 express:让单页项目从 npm init 跑到能响应请求
9 月 4 日装 node.js 并npm init,9 月 5 日装 express 打通 get/post,9 月 6 日装 mysql 辅助包把数据读出来。三天三个包,每一步都可能卡住,而且卡住时的报错信息都不太友好。
3.1 node.js 安装与 npm init 的两个关键字段
安装本身没有太多讲究,装完先验版本,两个命令都要有输出。项目根目录按记录里的做法新建文件夹即可,但要避开中文和空格——npm init在带空格的路径下生成的name字段会非法,后面npm install直接报错。
node -v npm -v mkdir teacher-page && cd teacher-page npm init -y-y是全部取默认值,省掉一路回车。生成的package.json里,name只能是小写字母、数字、连字符,不能有大写和中文;main是入口文件,默认index.js,如果你写的是server.js,这里必须改成server.js,否则npm start找不到文件。scripts.start里填node server.js,以后启动统一用npm start,不用记文件名。
# --save 在 npm 5 之前是必须写的,否则依赖不会进 package.json npm install express --save npm install mysql --save装完会多出node_modules目录,这个目录不能进版本库,体积大且与平台相关,靠package.json里的dependencies还原就够了。如果内网访问公共源很慢,把源指到可用的镜像上再装,不要在一个卡住的npm install上反复重试。
3.2 express 的 get 与 post,别把参数取错地方
记录里说花了大半天才摸清 get 和 post 怎么取数据,这半天不冤。get 的参数在 URL 上,取req.query;post 的参数在请求体里,没中间件解析就是undefined。这两者的区别被记错一次,调接口时会一直以为前端没传值。
const express = require('express'); const app = express(); // 4.16 之前要单独装 body-parser,之后内置,这一行就是版本分水岭 app.use(express.urlencoded({ extended: true })); let teachers = []; // GET 取列表,参数从 query 里拿 app.get('/teacher', (req, res) => { const keyword = req.query.name || ''; res.json(teachers.filter(t => t.name.includes(keyword))); }); // POST 新增,参数从 body 里拿 app.post('/teacher', (req, res) => { const { id, name, course } = req.body; teachers.push({ id, name, course }); res.json({ ok: true, total: teachers.length }); }); app.listen(3000, () => console.log('http://127.0.0.1:3000'));extended: true允许嵌套对象,false只支持字符串和数组,教学项目里两者都行,但和前端传参格式要对上。app.listen的 3000 被占用时会抛EADDRINUSE,换个端口就行,这和后文 Tomcat 的端口冲突是同一类问题。另外res.json会自动设置Content-Type,别手动拼字符串。
3.3 连 MySQL:mysql 包、连接池和 JSON 回显
记录里 9 月 6 日的顺序是先建库建表、把表格数据导进去,再装 node 的 mysql 辅助包读数据。顺序是对的,反过来的话你连表名都对不上。连接对象建议直接用连接池,别每次查询都新建连接,测试阶段没事,压几十个请求就会Too many connections。
const mysql = require('mysql'); const pool = mysql.createPool({ host: '127.0.0.1', port: 3306, user: 'root', password: '你的密码', database: 'school', charset: 'utf8mb4', // 这一行和后面的中文乱码直接相关 connectionLimit: 10 }); // pool.query 会自动取连接并归还,不需要手动 release pool.query('SELECT id, name, course FROM teacher', (err, rows) => { if (err) throw err; console.log(JSON.stringify(rows)); // 转成 JSON 直接回给页面 });connectionLimit默认是 10,教学项目够用,调大之前先确认数据库的max_connections。charset不写默认是utf8,遇到四字节字符(比如某些生僻字、表情)会截断,这也是为什么现在统一建议utf8mb4。只有用pool.getConnection()手动取连接时才需要release(),忘了释放比连接不够更常见。
3.4 增删改查落在按钮上:重复回显的修法
9 月 3 日那条记录写了个很典型的问题:点几次添加,页面上就叠几份数据。原因是渲染函数只往后追加,没有先清空容器。9 月 7 日实现增删改查时,本质还是同一件事——按钮点击触发不同函数,函数拼不同的 SQL。
function render(list) { const tbody = document.querySelector('#tb tbody'); tbody.innerHTML = ''; // 先清空,否则每次都会叠加一份 list.forEach(t => { const tr = document.createElement('tr'); tr.innerHTML = `<td>${t.id}</td><td>${t.name}</td><td>${t.course}</td>`; tbody.appendChild(tr); }); }先清空再渲染,数据量小的时候最省事;列表很长时整段重建会闪一下,那就得做增量更新或者虚拟滚动。教学项目里不用上那么重,但“先清空”这个习惯要留住,不然做删除功能时页面会越来越乱。删除和修改同理,别把按钮的跳转写成href直连 jsp,中间加一层脚本判断,操作失败还能提示。
4. MySQL 与 Tomcat:库表落地、项目上线与 IIS 本地站点
这一段是整套环境里最容易反复失败的地方,记录里 9 月 20 日到 9 月 28 日几乎天天在装东西。数据库装不上、中文写不进去、项目部署后 404、端口被占用、IIS 站点打不开,五个问题占了实习后半程的大半时间。
4.1 安装 MySQL:那个「开发者」选项不是随便选的
9 月 21 日那条记录说得很清楚:数据库装不上,原因是安装过程中没选“开发者”选项,同事一点就通了。安装向导里那几种 Setup Type 的区别是:Developer Default 会带上服务端、客户端和开发用组件;Server only 只有服务端;Client only 只有客户端工具;Custom 自己勾。只装客户端却想启动服务,必然失败。
# Windows 上先确认服务真的起来了,再谈连不连得上 sc query MySQL # 能连上再验版本,密码在安装时设的那个 mysql -uroot -p -e "SELECT VERSION();" # Linux 上的写法 systemctl status mysqld安装时还有两个参数要留意:端口默认 3306,被别的实例占了就换成 3307;字符集在安装向导里能选,选默认的 latin1 会给你后面添一堆麻烦。root 密码设完记下来,忘了只能走跳过权限表重置那套流程,生产机器上别轻易试。
4.2 建库建表与字符集:三处必须一致
9 月 21 日中文写不进去,在连接代码里加了限定字符集解决;9 月 26 日回显又乱码,把数据库和页面都改成 gbk 才好。两次都是编码,说明乱码从来不是一处的问题——服务端、库表、连接这三处的字符集只要有一处不一致,中文就会变成问号或者乱码。
-- 建库时就定字符集,别等出了问题再 ALTER CREATE DATABASE bookshop DEFAULT CHARACTER SET utf8mb4; CREATE TABLE book ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(64) NOT NULL, price DECIMAL(8,2) DEFAULT 0.00 ) DEFAULT CHARSET=utf8mb4; -- 三处都要看一眼,全一致才算干净 SHOW VARIABLES LIKE 'character_set%';当年改 gbk 是权宜之计,为了兼容老页面和老的数据库客户端工具。现在没有历史包袱的话,统一utf8mb4更省事:gbk存不了四字节字符,跨平台迁移时还得再转一次。JDBC 连接串上也要显式声明,否则驱动按服务端默认来:jdbc:mysql://127.0.0.1:3306/bookshop?useUnicode=true&characterEncoding=utf8。
4.3 表格数据导入与中文校验
记录里的做法是新建库、新建表,再把表格数据导进去。数据量不大的话,用客户端工具的导入向导最快;数据量大或者要重复执行,就走LOAD DATA,把表格另存成 CSV 更稳。
-- 导入前先确认 local_infile 已开启 LOAD DATA LOCAL INFILE '/tmp/book.csv' INTO TABLE book FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES; -- 导完必须查中文,别只看行数 SELECT * FROM book WHERE name LIKE '%数据库%';IGNORE 1 LINES跳过表头,ENCLOSED BY '"'处理字段里有逗号的情况。导入完成后只查COUNT(*)是不够的,行数对得上、中文全是问号的情况太常见了。我的习惯是导完立刻按中文关键字查一次,查得到才算这一步过。
4.4 Tomcat:webapps 目录、89 端口和 URIEncoding
记录里 9 月 28 日把项目挪到 Tomcat 下的wabapp目录,这个拼写是笔误,真实目录名是webapps,写错了访问就是 404,而且日志里不一定有明显提示。配置文件里改端口那段也别照抄 89——小于 1024 的端口在 Linux 上要 root 权限才能绑定,本地开发用 8080 或者 8089 更省心。
<!-- conf/server.xml,改完必须重启才生效 --> <Connector port="89" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />URIEncoding="UTF-8"管的是 URL 上的中文参数,不加这行,get 请求里的中文到后端就是乱码,post 反而不受影响——这个不对称经常把人绕晕。项目放进去之后,访问地址是http://ip:89/项目名/index.jsp,项目名就是webapps下那个文件夹的名字,改文件夹名等于改访问路径。
4.5 MyEclipse 关联 Tomcat 与驱动 jar 的配对
9 月 13 日那条 500 错误记录,是整份材料里排查难度最高的一条:Tomcat 配置改了很多遍都没用,最后发现是 jar 包和数据库版本不匹配导致连不上。这类问题的正确排查顺序是先看日志再改配置,日志里出现“数据加载失败”,说明连接阶段就已经失败,跟 Tomcat 的端口、路径都没关系。
# 驱动 jar 要随项目走,放在 WEB-INF/lib 下,不能只加在 IDE 的 Build Path 里 ls WebContent/WEB-INF/lib | grep -i -E "mysql|sqljdbc"只加 Build Path 的结果是本机能跑、部署到服务器就 500,因为服务器上没有你 IDE 里的那份路径。驱动版本要和服务端大版本对上,老版本驱动连新版本数据库会报协议不匹配,反过来也一样。连接池配置里的driverClassName拼错一个字母,同样是 500,日志里会明确写ClassNotFoundException,看到这条就别再怀疑网络了。
4.6 IIS 本地站点:设了主目录还是打不开
9 月 12 日那段记录,问题现象是装好 IIS、设了默认网站的主目录,浏览器里访问仍然打不开。原因是本地虚拟访问要走 IIS 的来宾账户,目录权限没给,请求直接被拒。另一个细节是必须在 NTFS 格式的磁盘上才有“安全”选项卡,FAT32 的盘上找不到这个入口,网上很多答案没说这一句,照着做会一直找不到地方。
:: 给来宾账户读和执行的权限,后台管理需要写入再加 (M) icacls "D:\wwwroot" /grant "IUSR:(OI)(CI)(RX)"(OI)是对象继承、(CI)是容器继承,两个都加上,子目录才一起生效;(RX)是读加执行,(M)是修改。只给顶层目录不给继承,二级目录照样 401。权限收得太紧会 401,放得太松又不安全,本地开发给到读执行就够,需要后台写文件时再单独给某个子目录加修改权限。
5. 排查清单:装完这套环境最容易遇到问题的五处
这几条都是从这份记录里能对上号的问题,加上我自己重装时又遇到一遍的。每条按现象、原因、解决写,照着核对一遍,能省掉大半天。
5.1 启动 Tomcat 报端口被占用
现象:Tomcat 一闪而过,或者浏览器访问项目地址只返回连接被拒绝,日志里能看到Address already in use。
原因:89 端口被别的进程占了,可能是上一次没关干净的 Tomcat 实例,也可能是别的服务在用。
解决:先查占用者,再决定是杀进程还是换端口,别一上来就改配置。
# Windows netstat -ano | findstr :89 # Linux ss -lntp | grep 89确认 PID 后结束对应进程,或者把server.xml里的端口改成 8089 之类没人用的值,重启验一次。
5.2 页面报 500,日志里是“数据加载失败”
现象:项目能启动,index.jsp一访问就 500,堆栈里提示数据加载失败。
原因:数据库驱动 jar 与数据库版本不匹配,或者驱动 jar 只在 IDE 的 Build Path 里、没进WEB-INF/lib。
解决:把匹配版本的驱动 jar 复制到WEB-INF/lib,清理 Tomcat 的work目录重新部署。还不行就看日志第一行的异常类型,ClassNotFoundException和连接超时是两回事。
5.3 中文写进数据库变成问号
现象:页面上输入中文,插入成功,查出来全是???。
原因:连接串没声明字符集,或者库表字符集是 latin1,跟页面编码不一致。
解决:三处对齐成utf8mb4,连接串加useUnicode=true&characterEncoding=utf8。已有脏数据只能重新导,改字符集不会把问号变回汉字。
5.4 javac 报“编码 GBK 的不可映射字符”
现象:源码里带中文注释,编译直接失败,javac 报不可映射字符。
原因:源文件是 UTF-8,系统默认编码是 GBK,编译器按默认编码去读。
解决:编译时显式指定编码,一次到位。
javac -encoding UTF-8 -d out src/com/shixi/main/Main.javaEclipse 里同理,把工作空间的 Text file encoding 统一成 UTF-8,别一个项目一种编码。
5.5 npm install 卡住或者报错退出
现象:命令执行后长时间没输出,或者直接报网络相关的错误。
原因:默认源在本地环境访问不通,或者路径里有中文和空格导致包名解析失败。
解决:先把项目挪到纯英文路径,再换可用源重试。node_modules删掉重装比在坏目录里反复npm install快得多。这里没什么捷径,就是换路径、清缓存、重装三步。
6. 验证一遍再交:七步确认六套环境真的跑通了
装完不等于跑通。这份记录最值得学的地方,是每天结尾都写了“功能成功实现”或者“访问失败”,有明确的判断标准。我自己重装完之后会按下面这个顺序过一遍,任何一步输出不对就停下来修,不往下走。
| 顺序 | 验证动作 | 正常结果 |
|---|---|---|
| 1 | java -version与javac -version | 两行版本号完全一致 |
| 2 | java -jar FileTool.jar | 弹出 Swing 面板,能查到文件 |
| 3 | npm start | 控制台打印监听地址,无 EADDRINUSE |
| 4 | curl http://127.0.0.1:3000/teacher | 返回 JSON 数组,中文正常显示 |
| 5 | mysql -e "SHOW VARIABLES LIKE 'character_set%'" | 三处字符集均为 utf8mb4 |
| 6 | 浏览器访问http://ip:89/项目名/index.jsp | 页面正常渲染,无 500 |
| 7 | 浏览器访问 IIS 站点 | 首页能打开,后台目录可写 |
第 4 步用 curl 而不是直接开浏览器,是因为它能把响应体原样打出来,中文乱码一眼就能看见。第 6 步如果 500,先看 Tomcat 的logs/catalina.out最后二十行,再回头对第 4 章里驱动 jar 的位置。
# 接口自检:先看状态码,再看内容 curl -i http://127.0.0.1:3000/teacher # 部署自检:直接看日志尾部,比猜快 tail -n 20 logs/catalina.out真正的验证顺序应该反过来:先确认数据库里躺的是正确的中文,再确认接口能读出来,最后才看页面渲染。倒过来查,页面一白屏你会不知道是 SQL 写错、连接串错还是前端渲染错,只能一层层加日志。血泪经验是:把每一层都单独验一遍,别指望一次跑通再看日志猜。
从那以后,我每次装完一套环境,都会按这个表从头到尾走一遍再交付,中间任何一步跳过,后面必然要返工。这份《软件工程实习记录》里最有价值的就是这些具体参数和失败现场,写实习报告时稍作修改就能用,照着复现也能少走很多弯路。希望帮到你。
本文还有配套的精品资源,点击获取