ARTICLE DETAIL

资讯详情

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

校园二手交易市场Java课设:Servlet+JSP+MySQL从建表到交付全攻略

校园二手交易市场Java课设:Servlet+JSP+MySQL从建表到交付全攻略 简介这是一份面向大二小学期的Java程序设计实践项目主题为校园二手交易市场适合计算机相关专业学生用于课程设计、小学期实训或毕业设计参考。资源包共223个文件包含37个Java源文件、24个HTML页面、21个XML配置、CSS样式与JavaScript脚本以及大量jpg/png图片素材压缩包约9.97MB目录结构清晰便于直接导入IDE运行。同时附带系统设计文档和使用须知可帮助读者快速梳理用户登录、商品发布、浏览下单、信息管理等核心模块的业务流程与实现思路所有源码均经过严格测试可直接运行。目前已有61人学习下载对需要完整Web项目案例或二手交易系统开发参考的同学具有较高参考价值。1. 大二小学期Java程序设计实践校园二手交易市场.zip 到底是什么、在考什么每年小学期最常被问的一句话就是“别人都把项目跑起来了我还在配环境”。而这个校园二手交易市场.zip正是大二Java程序设计实践课最常见的交付物一份包含完整源码、数据库脚本、文档和演示路径的压缩包。课程老师不会只看界面漂不漂亮真正决定成绩的是你拿到zip后能不能当场演示、能不能说清每个类的职责。做这个项目能解决一个很实际的问题把Java基础语法、集合、JDBC、Servlet、JSP、Session和MySQL这些零散知识点串成一条完整的Web开发链路。适合正在做大二课程设计、Java基础刚过关、想交出一份不丢人作业的同学。看完这篇你能从建表一路写到打包交付中间那些让你半夜翻车的坑我会按踩过的顺序一个个点名。2. 技术选型先定死这三件事ServletJSP 还是 Spring Boot课程设计选哪条路最稳2.1 课程设计评审到底看什么先按验收项倒推工期小学期的项目不是企业项目老师验收时手上有几张固定的检查表。第一项是“能不能跑”签到时现场打开浏览器注册一个账号、发一件商品、再买一件商品五秒钟之内见真章第二项是“代码是不是你自己写的”老师会随机点开一个类问你“这个接口为什么这么设计”第三项是“表结构是否合理”一把拉出数据库里的表看有没有主外键关系、金额字段用没用对类型。按这三条倒推你真正需要投入的时间其实是建模半天、核心功能两天、页面打磨一天半、文档和打包一天总共五天左右就能达到中等偏上水平。如果选错技术栈光环境问题就能耗掉两天。所以选型这件事不是看哪个框架更现代而是看哪个方案能在最短时间内让你把每个模块都讲得清楚。2.2 三套选型放在一起比上手速度、答辩追问风险、简历成色大二课设常见的路线就三条ServletJSP 手工搭建、Spring BootThymeleaf、以及现成的若依之类的快速脚手架。对Java程序设计实践这门课来说我推荐第一条。选型方案上手周期答辩被追问的风险简历成色ServletJSPJDBC约2~3天低每个类自己写的能讲清Java Web基础适合校招前期Spring BootThymeleaf约3~5天中容易被问自动配置原理更贴近生产环境但课设深度难体现快速脚手架若依等半天起高一问代码来源就露馅不建议写进简历这里有个反直觉的结论Spring Boot本身不复杂复杂的是它帮你自动干完的那些事。课程设计答辩时老师最爱问“这个配置是怎么生效的”“为什么加一个依赖就可以用了”你要是没读过自动配置源码回答时就会变成“好像就可以了”这一下就把印象分拉下来了。而ServletJSP这套方案里过滤器、监听器、连接池、DAO都是你自己写的被问到“继承和接口在哪个类里面有体现”你能直接指出来这就是面向对象编程java这门课最想要的答卷。2.3 环境准备一条命令都别省JDK、MySQL 8.0 zip 版、驱动版本环境问题占了课设踩坑的一半。先说JDK安装完成后一定在命令行验证一下IDE里能跑不等于命令行能跑因为Tomcat启动脚本走的是系统环境变量。然后是MySQL很多同学装MySQL图省事用exe向导结果密码忘了、服务没启动还找不到日志。其实MySQL官方提供zip免安装版解压就能用步骤反而比向导更可控网上搜“mysql8.0 zip windows10 安装教程”已经是一套成熟流程了。# 验证JDKjavac存在才能编译Servlet java -version # 如果你的mysql是zip版先解压到D:/mysql-8.0.x-winx64 # 管理员身份打开CMD先初始化数据目录 mysqld --initialize-insecure --basedirD:/mysql-8.0.x-winx64 --datadirD:/mysql-8.0.x-winx64/data # 注册成Windows服务注意服务名别默认防止和已有MySQL冲突 mysqld --install MySQL8 --defaults-fileD:/mysql-8.0.x-winx64/my.ini # 启动服务 net start MySQL8--initialize-insecure的意思是初始化一个root密码为空的实例后续自己再改密码免得你在安装向导里被密码规则卡住。《--defaults-file 参数指定配置文件位置my.ini里必须写清楚basedir和datadir否则服务起来后找不到数据目录。驱动版本是个血泪经验。连接MySQL 8.0必须用com.mysql.cj.jdbc.Driver而不是老教程里的com.mysql.jdbc.Driver。如果用的是课程提供的旧版mysql-connector-java 5.x初始化时能加载驱动一执行查询就报Unable to load authentication plugin caching_sha2_password。这个坑后面第5章专门展开先在pom或lib目录确认jar包版本在8.0以上。3. 从建库到跑通核心表结构、登录注册、商品发布与图片上传3.1 数据模型核心表字段设计别把状态写成字符串校园二手交易市场本质上是一个“商品用户订单”的三元模型。很多同学一上来就建七八张表最后关联查询把自己绕晕。我的习惯是只建六张必要的表用户表、商品表、分类表、订单表、收藏表、留言表。后面的收藏和留言是加分项前面四张是必选项。表名职责关键字段t_user买家卖家一体id, username, password, email, create_timet_goods二手商品id, seller_id, category_id, title, price, image_url, statust_category商品分类id, namet_order交易订单id, goods_id, buyer_id, price, status, create_timet_favorite收藏id, user_id, goods_id, create_timet_message商品留言id, goods_id, user_id, content, create_time建表时有两个习惯是加分项。第一表名不要叫user或order这两个词在MySQL里容易撞保留字统一加t_前缀省心第二状态字段用TINYINT不用VARCHAR“在售/下架/已售”这种状态值本质是枚举用数字存能省空间还避免中文编码问题。CREATE TABLE t_goods ( id INT AUTO_INCREMENT PRIMARY KEY, seller_id INT NOT NULL COMMENT 发布者ID关联t_user.id, category_id INT NOT NULL COMMENT 分类ID关联t_category.id, title VARCHAR(100) NOT NULL COMMENT 商品标题, description TEXT COMMENT 详细描述TEXT类型足够存放一段话, price DECIMAL(10,2) NOT NULL COMMENT 价格带两位小数, image_url VARCHAR(255) DEFAULT COMMENT 商品图片的相对访问路径, status TINYINT NOT NULL DEFAULT 1 COMMENT 0下架 1在售 2已售, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_seller (seller_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品表;价格字段是新手最容易翻车的地方。浮点数float和double在二进制里无法精确表示定价59.9元的商品经过计算可能变成59.899999这在订单对账时能算出差一分钱的问题。所以价格一律用DECIMAL(10,2)第一位参数10表示总位数2表示小数位数课程设计里撑到上亿价格足够。索引方面给seller_id和status分别建普通索引就够了商品列表页的查询条件无非是“某个人发布的所有商品”和“状态为1的在售商品”这两个索引正好命中。初始化数据时顺手把分类表填上后面页面下拉框直接查这张表。INSERT INTO t_category (name) VALUES (教材教辅), (电子产品), (生活用品), (运动户外), (其他);3.2 注册、登录与 Session 拦截完整代码与参数说明登录注册是项目门面也是老师最喜欢考核的一个模块。先写数据库访问层连接信息集中放在DBUtil里不要在十个类里各写一份DriverManager.getConnection。public class DBUtil { // serverTimezoneAsia/Shanghai 必须写MySQL 8.0 默认时区与JDBC不一致 private static final String URL jdbc:mysql://localhost:3306/campus_market?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { throw new RuntimeException(MySQL驱动加载失败检查jar包版本, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }URL里那串参数不是玄学。characterEncodingutf8解决中文写入乱码useSSLfalse避免本地连接时SSL握手告警刷屏serverTimezoneAsia/Shanghai如果不写MySQL 8.0会报连接失败的时区错误这是所有MySQL 8新手的第一道坎。把连接参数都写在常量里之后换机器只需改这四个参数课设文档里也好解释。注册Servlet的写法决定了答辩时老师怎么评价你。这里有个细节表单校验失败时用请求转发而不是重定向因为转发是服务器内部跳转request里设置的错误提示能带到JSP页面显示。WebServlet(/register) public class RegisterServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String username req.getParameter(username); String password req.getParameter(password); String email req.getParameter(email); // 基础校验用户名3-20位密码至少6位 if (username null || username.trim().length() 3 || password null || password.length() 6) { req.setAttribute(error, 用户名需3-20位密码至少6位); req.getRequestDispatcher(/WEB-INF/register.jsp).forward(req, resp); return; } UserDao dao new UserDao(); boolean ok dao.register(username, Md5Util.md5(password), email); if (ok) { resp.sendRedirect(req.getContextPath() /login); } else { req.setAttribute(error, 用户名已存在换一个试试); req.getRequestDispatcher(/WEB-INF/register.jsp).forward(req, resp); } } }密码加密这块是答辩高频问题。明文存密码一旦被质疑你就很难圆场直接说自己做了哈希处理就能过关。MD5虽然按现在的标准不算强加密但在课程设计里足够如果能补一句“生产环境应该用BCrypt这类加盐哈希”这个回答就是加分项。Md5Util.md5()内部用MessageDigest.getInstance(MD5)生成32位十六进制字符串正好对应数据库里CHAR(32)的长度。登录成功后把用户对象放进Session注意只放id、用户名这类的必要信息不要把密码字段也塞进对象。一个简单的做法是session.setAttribute(currentUser, user)同时在User对象里把password字段标成JsonIgnore或干脆用VO类。WebServlet(/login) public class LoginServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String username req.getParameter(username); String password req.getParameter(password); // 先查一次再比对避免登录失败和请求错误混在一起 User user new UserDao().findByUsernameAndPassword( username, Md5Util.md5(password)); if (user null) { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(/WEB-INF/login.jsp).forward(req, resp); return; } HttpSession session req.getSession(); session.setAttribute(currentUser, user); resp.sendRedirect(req.getContextPath() /index); } }这里特意用“先查库再比对”而不是“拉出密码用equals比对”是为了让DAO层更简洁。SQL写成WHERE username? AND password?参数化查询既防SQL注入也避免把用户不存在和密码错误两种情况分开枚举。3.3 商品发布与图片上传multipart 配置和文件落盘路径商品发布是二手交易市场的核心动作比登录注册复杂在它要处理图片上传。表单必须声明enctypemultipart/form-data否则浏览器只会把文件名作为普通字符串传过来后台拿不到文件流。图片上传的Servlet要加MultipartConfig注解三个参数的含义必须能答上来。maxFileSize限制单张图片大小防止有人传几个G的文件把服务器撑爆maxRequestSize限制整个表单请求体大小location是文件落盘的根目录默认走Tomcat临时目录会丢文件必须指定一个稳定的绝对路径。WebServlet(/publish) MultipartConfig( location D:/campus_upload/, maxFileSize 5 * 1024 * 1024, maxRequestSize 50 * 1024 * 1024 ) public class PublishServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String title req.getParameter(title); BigDecimal price new BigDecimal(req.getParameter(price)); int categoryId Integer.parseInt(req.getParameter(categoryId)); HttpSession session req.getSession(false); // 发布本来就是登录后才能做的动作这里再校验一次更严谨 if (session null || session.getAttribute(currentUser) null) { resp.sendRedirect(req.getContextPath() /login); return; } Part part req.getPart(image); String fileName extractFileName(part); // 文件名加时间戳避免两个用户传同名文件互相覆盖 String savedName System.currentTimeMillis() _ fileName; String webPath /upload/ savedName; part.write(D:/campus_upload/ savedName); Goods goods new Goods(); goods.setTitle(title); goods.setPrice(price); goods.setCategoryId(categoryId); goods.setImageUrl(webPath); // 数据库存访问路径不存磁盘绝对路径 goods.setStatus(1); // 1在售发布默认直接上架 new GoodsDao().insert(goods, (Integer) session.getAttribute(currentUserId)); resp.sendRedirect(req.getContextPath() /index); } }extractFileName这个工具方法要从Part的header里抠文件名因为不同浏览器传上来的header格式有差异。核心逻辑是先取content-disposition头再按filename切割然后处理路径分隔符取最后一段。写完后最好在Chrome和Edge各测一次上传。数据库里存image_url这一列我存的是/upload/xxx.jpg这种相对访问路径而不是D:/campus_upload/xxx.jpg。原因是页面渲染时直接用项目根拼上相对路径就能访问而如果存绝对路径一旦把项目拷到别人电脑上路径瞬间失效。要把磁盘路径对外暴露成一个URL还需要在Tomcat的server.xml里配一个虚拟目录映射这一步放到第5章踩坑清单里细说。4. 把订单状态流转和权限边界写清楚让老师答辩时放心给你加分4.1 订单状态机四个状态的合法流转拒绝乱改状态订单状态是二手交易市场里最容易被写乱的部分。很多同学用一堆if else在Servlet里直接改状态导致数据库里出现“已付款的商品还在售”这种逻辑漏洞。正确做法是先定义一张状态流转表代码里只允许合法跳转。状态值含义允许流转到0待付款1付款、3取消1已付款待发货2确认收货、3退款取消2已完成无3已取消无商品状态和订单状态是两套独立的状态但两者要联动。下单成功后商品状态从1在售改成2已售订单取消后商品状态要回滚成1继续可售。这个联动逻辑放在Service层里用事务包起来避免中间某一步失败导致状态不一致。WebServlet(/order/create) public class CreateOrderServlet extends HttpServlet { Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); HttpSession session req.getSession(false); User currentUser (User) session.getAttribute(currentUser); // 价格不能从页面传要重新从数据库查防止客户端改价 int goodsId Integer.parseInt(req.getParameter(goodsId)); GoodsDao goodsDao new GoodsDao(); Goods goods goodsDao.findById(goodsId); // 校验商品必须存在且在售这是最关键的一步 if (goods null || goods.getStatus() ! 1) { req.setAttribute(error, 商品不存在或已下架); req.getRequestDispatcher(/goods/detail?goodsId goodsId).forward(req, resp); return; } OrderDao orderDao new OrderDao(); // 事务方法创建订单 改商品状态 boolean ok orderDao.createWithLock(goods, currentUser.getId()); if (ok) { resp.sendRedirect(req.getContextPath() /orders/list); } else { req.setAttribute(error, 下单失败请重试); req.getRequestDispatcher(/goods/detail?goodsId goodsId).forward(req, resp); } } }注意一个细节页面表单里不要出现price参数下单时价格一律重新从商品表查。这是面试里常被问的“数据一致性”问题的课设版体现。createWithLock内部先执行SELECT ... FOR UPDATE锁定商品行再插入订单记录并更新商品状态。这么写不仅解决了超卖答辩时还能顺势讲一句“这里用了行级锁防止并发下单”老师对你的代码评估会明显上一个档次。4.2 用Filter统一做权限控制Session为空直接打回权限控制应该是项目里重复代码最少的地方。小学期项目常见的错误是每个Servlet开头都粘一段“判断Session是否为空”的代码七八个类里复制粘贴改一处漏一处。Java Web的标准答案是写一个过滤器把需要登录才能访问的URL全部拦截。WebFilter(urlPatterns {/publish, /orders/*, /favorite/*, /message/*}) public class AuthFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; // getSession(false) 不创建新会话避免给未登录用户制造空Session HttpSession session req.getSession(false); if (session null || session.getAttribute(currentUser) null) { // 未登录的打回登录页并记录原始路径登录后跳回 resp.sendRedirect(req.getContextPath() /login); return; } // 已登录则放行进入后面的Servlet或JSP chain.doFilter(req, resp); } }urlPatterns里用通配符*批量拦截一组路径。不用把所有路径都列进来登录和注册页面本来就要匿名访问首页和商品详情页也不用拦——浏览商品是游客就该有的权限。这里体现出来的边界感答辩时是能讲出东西的哪些放行、哪些拦截、为什么这样划分。如果你的项目里还有“卖家不能购买自己商品”这类业务规则不要放进Filter。Filter只解决“有没有登录”这一层问题具体到“是不是本人”要在Service层里判断。把这两层权限分开代码职责就清晰了老师问起“权限是怎么控制的”你可以分两级回答。4.3 分页和搜索的SQL写法列表页不卡、答辩有话聊商品列表页如果一次把所有商品都查出来数据量小的时候看不出问题但老师一句“如果有一万条商品呢”就能把你问住。分页是课程设计的必考点也是以后javascript和java面试八股文里反复出现的基础能力。public ListGoods findPage(int page, int pageSize) { // LIMIT 第一个参数是偏移量第二个参数是返回条数 String sql SELECT * FROM t_goods WHERE status 1 ORDER BY create_time DESC LIMIT ?, ?; ListObject params new ArrayList(); params.add((page - 1) * pageSize); // 第1页偏移0第2页偏移pageSize params.add(pageSize); return queryList(sql, params); } public int countOnSale() { String sql SELECT COUNT(*) FROM t_goods WHERE status 1; // 总页数 (总条数 pageSize - 1) / pageSize }分页参数设计的常见问题是页数用page和pageSize两个变量还是用offset。我建议Controller层接收页码和每页条数在DAO层换算成偏移量。这样页面和用户交互更友好地址栏显示的是?page3而不是?offset20。每页条数不要超过20二手商品列表最重要的是在“首屏”内给出有效信息。搜索功能在分页基础上加一个LIKE条件就行。关键点是只查“在售”状态的商品并且对搜索词做合理的字符串处理去首尾空格、限制最短长度。SQL里用LIKE CONCAT(%, ?, %)而不是直接拼接否则搜索词里带%会把整表扫出来这也是一个能讲半天的细节。5. 校园二手交易项目最常翻车的五类问题踩坑排查清单5.1 中文乱码请求和响应编码分开设Filter别只设一半现象注册时用户名填“小明”存进数据库变成“灏忔槑”页面显示一堆问号。原因客户端提交表单用的UTF-8服务器端默认用ISO-8859-1解码两端字符集不一致导致乱码。更隐蔽的是只设置了请求编码没设置响应编码JSP页面输出的标题正常但动态内容全是问号。解决写一个全局编码Filter放在所有业务Filter的最前面同时处理请求和响应两端。WebFilter(urlPatterns /*) public class EncodingFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding(UTF-8); resp.setCharacterEncoding(UTF-8); resp.setContentType(text/html;charsetUTF-8); chain.doFilter(req, resp); } }另外JSP页面顶部的pageEncoding也必须是UTF-8数据库连接串里的characterEncodingutf8和建表时的CHARSETutf8mb4三层都对齐一个字符都不会乱。5.2 MySQL 8.0连不上驱动jar太旧和serverTimezone缺失现象启动Tomcat后一访问商品列表页就报Unable to load authentication plugin caching_sha2_password或者直接抛Connection refused。原因MySQL 8.0默认认证插件换成caching_sha2_password旧版mysql-connector-java 5.x不支持。另一个常见理由是驱动类加载了但连接串里没写时区MySQL 8.0对时区要求比5.x严格得多。解决把lib目录下的驱动jar换成mysql-connector-java-8.0.x.jar连接串改成完整版。jdbc.urljdbc:mysql://localhost:3306/campus_market?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8 jdbc.usernameroot jdbc.password123456如果确认都改了还连不上检查MySQL服务是否真的启动了。用net start | findstr MySQL看服务列表到服务窗口把MySQL8启动类型改成“自动”免得重启电脑后又白屏。5.3 图片上传后前端打不开本地路径和虚拟路径不一致现象上传图片时提示成功数据库里也能看到一条image_url记录但浏览器访问商品的图片链接返回404。原因数据库里存的是D:/campus_upload/xxx.jpg而Tomcat能访问的路径必须是项目根目录下的资源或者配置文件里声明的虚拟路径。浏览器请求/upload/xxx.jpg时Tomcat根本不知道这个路径映射到磁盘哪里。解决路径存储和对外访问分开——数据库只存访问路径/upload/xxx.jpg磁盘文件放在D:/campus_upload/然后在Tomcat的conf/server.xml的Host节点下加一个Context映射。Context docBaseD:/campus_upload path/upload reloadablefalse/这个配置的意思是用户访问/upload/1.jpg时Tomcat从D:/campus_upload/1.jpg读取文件。注意给目录设置可读权限Windows下默认没问题Linux下要chmod 755。如果用的是IDEA内置Tomcat改server.xml之后必须重启才能生效。5.4 zip包里的文件解压失败或要密码交付前先解压一遍现象压缩包交上去之后老师解压时提示文件损坏或者双击zip弹出来一个密码输入框。明明在自己电脑上压缩得好好的。原因压缩工具版本和zip格式兼容性问题。用旧版WinRAR压出来的zip如果用7-Zip解压可能报头损坏更常见的是为了“保护源码”给zip设置了伪加密这种标记在部分解压软件上会触发密码框实际上文件并没有真正加密但老师已经没心情研究这个了。解决用zip格式压缩时统一选标准zip不要选rar或7z不需要加密课程设计的代码就是要给人看的。压缩完成后用系统自带的资源管理器解压到一个全新目录逐一遍历文件确认大小不为0、图片能打开。交付前在另一台电脑上做一次完整的“解压→导入数据库→启动Tomcat→演示”流程这一遍做完基本就稳了。5.5 Tomcat端口被占用项目明明没改页面却打不开现象上次还能正常启动的项目第二天一跑控制台报Port 8080 required by Tomcat ... is already in use。原因后台残留了前一次的Tomcat进程或者其它Java进程占用了8080端口。这种情况在IDEA里特别常见非正常关闭后进程还在端口被锁。解决Windows下用命令行查出占用8080的进程PID然后强制结束。netstat -ano | findstr 8080 taskkill /PID 这里填查到的PID /F更优雅的方案是把Tomcat端口改成避免冲突的值比如8090。改Tomcat的conf/server.xml里Connector port8080这一行顺带把项目启动的URL习惯改掉。答辩现场遇到端口被占用在老师的注视下手动kill进程再重启这比没有任何处理措施给人的印象好很多。6. 交付前按这份验证清单走一遍zip交出去不被打回6.1 一份能打分的zip内部结构课程设计项目的zip包结构最好一眼能看明白。三层目录源码、数据库脚本、文档和SQL放根目录不要套三层文件夹。目录/文件作用/srcJava源码按servlet、service、dao、util分包/WebContentJSP页面、WEB-INF、css、js/sql建表脚本和初始化数据命名为init.sql/README.md运行环境、启动步骤、测试账号/答辩PPT页面截图和功能列表源码分包时按controller / service / dao / entity / util五个包放一眼就能看出三层架构。README里写清楚JDK版本、MySQL版本、Tomcat版本和启动顺序这份文档能省掉老师一半的排查时间。6.2 换机跑通再压缩环境越接近“裸机”越可靠自己电脑上能跑不代表交上去能跑。我自己的习惯是压缩前最后一步把项目复制到一台没有装IDE的机器上用命令行启动Tomcat验证一遍。重点看两处数据库密码和连接串是不是写死在代码里、图片上传目录在目标机器上是否存在。如果连接信息写在db.properties里而不是Java类里换机器时改一个文件就够了。6.3 端口清理与路径检查两句命令能解决的绝不靠重装最后过一遍检查清单Tomcat能正常启动、8080端口未被占用、MySQL服务已启动、t_goods表里有种子数据、测试账号能登录。把项目从源目录复制出来时注意删掉IDEA生成的那些.idea和out目录压缩包大小会小一大截老师解压也不会被干扰。课程设计做到这个程度重点已经不是“能不能跑”而是“能不能稳定地跑给别人看”。把zip当产品交付先解压后启动所有路径都改成相对路径数据库脚本在全新实例上跑一遍。这个习惯我从大学带到现在工作后交付运维脚本依然复用的是同一套验证思路——你提交的不是一个压缩包而是一条能重复落地的路径。希望这篇能帮你在小学期少熬几个夜祝顺利。本文还有配套的精品资源点击获取
返回列表