ARTICLE DETAIL

资讯详情

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

JSP在线家政网课设全解析:从架构选型到订单权限实战

JSP在线家政网课设全解析:从架构选型到订单权限实战 简介基于JSP的在线家政网设计与实现文档是一份完整的课程设计与毕业设计参考方案重点面向Web开发方向的在校学生以及需要快速搭建家政服务平台的开发者。系统主要覆盖家政预约、家教预约、在线求职申请以及个人后台查询申请状态等核心功能整体采用B/S模式使用JSP技术完成页面生成与业务处理以SQL Server 2008作为后台数据库实现概念结构、逻辑结构和物理结构三个层面的设计并通过MyEclipse平台进行项目开发与调试。压缩包内为单个docx文档大小约1.02MB内容包含项目开发背景与意义、可行性分析、总体设计原则、结构化分析、各模块功能设计、数据库表设计及目录结构等章节能够完整呈现该系统从需求分析到设计实现的全过程适合作为同类型课题的设计蓝本也可为毕业设计说明书或课程论文提供现成的组织框架和文字素材。该资源目前已有126人学习下载对于正在完成JSP家政类网站选题或希望快速梳理B/S项目开发流程的读者具有直接参考价值。1. 在线家政网是个什么项目JSP技术栈里最耐打的课设选题如果说Spring Boot是现在Java Web的默认开场那JSP对于在线家政网这种以表单、列表、订单状态流转为主的中小型管理系统依然是开发周期最短的选项之一。这个标题背后是一套完整的课程设计或毕业设计原型用户注册登录、服务类别展示、家政人员信息、预约下单、订单流转、后台管理全部跑在JSPServletMySQL这条经典链路上。它解决的不仅是怎么把页面做出来更是一个带角色的业务系统怎么闭环。适合三类人需要交毕设或课设的在校生想快速搭一个内部演示系统的小团队开发以及想彻底搞懂Java Web请求链路的新手。JSP 在这个场景里被诟病过时但它把页面渲染和数据显示粘在一起单人开发时确实省事。接下来的内容按我做过同类方案的经验拆开讲从选型到建库、代码、踩坑一次性说清。2. 选型与架构为什么这个系统用JSP反而是最优解2.1 JSP在课设和内部项目中的真实定位很多人在选题时会纠结都2024年了为什么还用JSP答案是家政网这类项目对技术栈的要求是能快速实现CRUD、能演示、能答辩而不是能承受高并发。在线家政网的业务核心是用户下单、管理员派单、服务人员接单本质是一套多角色的信息管理系统。JSP页面可以直接嵌Java代码配合Servlet做控制层不用引入Spring的依赖注入和事务管理开发心智负担低得多。我见过太多人用Spring Boot做课设结果光搭环境就花了三周最后页面没写几张。倒不是说Spring Boot不好而是它对一个单人开发、周期两个月、要写论文的项目来说属于过度设计。JSP的另一个优势是便于现场演示修改JSP后Tomcat热部署就能看到效果不用像前后端分离那样同时开两个服务。这个项目如果放在真实生产环境JSP确实不是主流但它的价值在于快速验证业务逻辑而业务逻辑恰恰是家政网这类系统最值得花时间的部分。2.2 分层架构与请求流转从index.jsp到数据库的完整路径在线家政网的典型分层是五年之前Java Web课设就固定下来的四层结构JSP负责视图渲染Servlet负责接收请求和跳转Service层写业务规则DAO层用JDBC访问MySQL。我在做这类系统时会再加一个Entity层放实体类一个Util层放数据库连接工具和过滤器这样代码结构更清晰答辩时也好讲。一个用户登录的请求流转路径大致是这样的浏览器在index.jsp输入用户名密码表单提交到LoginServletServlet调用UserService的login方法Service内部再调UserDAO的findByUsername方法DAO执行PreparedStatement查询并返回User对象Service把结果返回给ServletServlet将User对象塞进session然后forward到home.jsphome.jsp用EL表达式${sessionScope.user.username}把用户名渲染到页面。整条链路里JSP只负责最后一步的展示业务判断全部收在Servlet和Service里。我一般建议把Servlet的路径统一设计成/servlet/LoginServlet这种带前缀的格式配合Filter做权限拦截时非常好写匹配规则。2.3 角色权限与项目目录结构先想清楚谁能干什么家政网至少有三个角色普通用户下单方、服务人员接单方、管理员审核、派单、统计。角色设计直接决定表结构和Filter怎么写。最简单的设计是用一张user表加role字段0代表普通用户1代表服务人员2代表管理员。前端JSP根据session里存的user.role判断显示哪些入口比如管理员才能看到用户管理菜单。目录结构我推荐按职责分包src下建com.housekeep.servlet、com.housekeep.service、com.housekeep.dao、com.housekeep.entity、com.housekeep.utilWebContent下建admin、user、common三个子目录分别放后台管理页、用户端页面、公共组件头部、底部。WEB-INF目录放web.xml和依赖的jar包之前踩过被扫到WEB-INF下JSP文件直接被Tomcat拒访问的坑所以所有页面都不要放WEB-INF里除非你想用Servlet forward来访问。2.4 权限拦截的Filter写法没有它你的系统等于裸奔权限控制是这类系统最容易偷懒的部分却是答辩评委最爱问的部分。我的建议是做一个LoginFilter拦截所有需要登录才能访问的Servlet和JSP。拦截规则用/servlet/*和/user/*两个路径再放行登录Servlet、注册Servlet和静态资源。这个Filter里要做三件事从session里取user对象取不到就重定向到login.jsp取到了再判断当前请求需要的角色和user.role是否匹配不匹配就跳转到401提示页。有一个细节容易忽略如果用户访问的是登录页本身再把他重定向到登录页会形成302循环所以Filter里必须先判断请求路径是否等于login.jsp是就直接放行。这个坑我在做第一个版本时踩过当时整个登录接口全部302跳转排查了半天才发现是Filter把自己拦了。3. 环境搭建与数据库设计从零到能跑的最小闭环3.1 开发环境版本搭配JDK8Tomcat8.5是保平安组合JSP项目对环境版本极其敏感不是越新越好而是越配套越好。我建议的组合是JDK 1.8 Tomcat 8.5 MySQL 5.7IDE用Eclipse或IDEA都行。这个组合最稳妥的原因在于JDK 8和Tomcat 8.5的兼容性经过了十几年验证网上能找到的JSP课设代码基本都跑在这套环境上。千万不要图新鲜用JDK 17搭配Tomcat 10因为Tomcat 10把javax.servlet包名改成了jakarta.servlet老项目里的import语句会全部报错这是JSP课设最常见的翻车点。如果你只有JDK 17那至少要把Tomcat固定到9.0.x版本它仍然用javax包名只是对较新JDK的支持没那么好。IDE里部署时注意Web Content目录要指向项目的WebContent文件夹部署的Context Path和项目名保持一致这个路径在之后所有页面的跳转中都会用到。3.2 建库建表四张核心表支撑起整个业务流程在线家政网的表结构不需要复杂五张表足够用户表、服务类别表、服务人员表、订单表、评价表。这里给出一份可以抄作业的建表SQL字符集统一用utf8mb4排序规则用utf8mb4_general_ci避免中文乱码。CREATE DATABASE IF NOT EXISTS housekeep DEFAULT CHARACTER SET utf8mb4; USE housekeep; CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE COMMENT 登录名, password VARCHAR(64) NOT NULL COMMENT MD5加密后的密码, real_name VARCHAR(50) DEFAULT NULL COMMENT 真实姓名, phone VARCHAR(20) DEFAULT NULL, address VARCHAR(200) DEFAULT NULL, avatar VARCHAR(200) DEFAULT NULL COMMENT 头像图片路径, role TINYINT NOT NULL DEFAULT 0 COMMENT 0普通用户 1服务人员 2管理员, status TINYINT NOT NULL DEFAULT 1 COMMENT 1正常 0禁用, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB COMMENT用户表; CREATE TABLE t_service_category ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL COMMENT 保洁/保姆/月嫂/维修, base_price DECIMAL(10,2) NOT NULL COMMENT 起步价, description VARCHAR(500) DEFAULT NULL, sort INT DEFAULT 0 COMMENT 排序字段小的在前 ) ENGINEInnoDB COMMENT服务类别表; CREATE TABLE t_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE COMMENT 订单编号时间戳随机数, user_id INT NOT NULL, service_id INT NOT NULL COMMENT 服务人员的用户ID, category_id INT NOT NULL, service_time DATETIME NOT NULL COMMENT 预约上门时间, address VARCHAR(200) NOT NULL, price DECIMAL(10,2) NOT NULL, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待支付 1待服务 2服务中 3已完成 4已取消 5退款, remark VARCHAR(500) DEFAULT NULL, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP ) ENGINEInnoDB COMMENT订单表; CREATE TABLE t_review ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL COMMENT 关联订单ID, user_id INT NOT NULL, service_id INT NOT NULL, content VARCHAR(500) DEFAULT NULL, score TINYINT NOT NULL DEFAULT 5 COMMENT 1到5分, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB COMMENT评价表;订单表的order_no字段一定要设UNIQUE因为业务上要拿它做查询依据重复会直接报错。price字段在订单表里单独存一份目的是把下单那一刻的价格固定下来服务类别表里的base_price以后调整了也不影响历史订单。status字段用整数而不是字符串是为了方便在Java里定义常量类避免订单状态散落在代码各处变成魔法数。3.3 JDBC连接池与DBUtil封装别再用DriverManager裸连如果直接在DAO里用DriverManager.getConnection每次查询都要创建和销毁连接家政网这种小项目虽然扛得住但并发一高就会报Too many connections。我当时做的时候直接用c3p0连接池配置非常简单不需要额外的容器支持。在src下建一个c3p0-config.xml内容如下c3p0-config default-config property namedriverClasscom.mysql.jdbc.Driver/property property namejdbcUrljdbc:mysql://localhost:3306/housekeep?useSSLfalseamp;characterEncodingutf8/property property nameuserroot/property property namepassword123456/property property nameinitialPoolSize5/property property namemaxPoolSize20/property property namecheckoutTimeout3000/property property namemaxIdleTime60/property /default-config /c3p0-config注意jdbcUrl里符号在XML中必须写成amp;这个坑会让连接池配置解析失败报错信息却非常隐晦。然后封装一个DBUtil类package com.housekeep.util; import com.mchange.v2.c3p0.ComboPooledDataSource; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class DBUtil { private static ComboPooledDataSource dataSource new ComboPooledDataSource(); public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } public static void close(Connection conn, Statement stmt, ResultSet rs) { try { if (rs ! null) rs.close(); } catch (SQLException ignored) {} try { if (stmt ! null) stmt.close(); } catch (SQLException ignored) {} try { if (conn ! null) conn.close(); } catch (SQLException ignored) {} } }initialPoolSize设为5、maxPoolSize设为20对课设系统足够checkoutTimeout设为3000毫秒意思是拿不到连接时最多等3秒避免页面长时间卡死。DBUtil关闭连接时要注意顺序先关ResultSet再关Statement最后关Connection虽然连接池的close方法实际是归还连接但释放顺序错了在某些版本下会报警告。4. 核心功能实现注册登录、预约下单与个人信息展示4.1 注册与登录PreparedStatement防注入MD5加密别裸存注册功能的代码不难但有两个点必须处理密码加密和SQL注入防护。JSP课设里最常见的写法是直接String sql insert into t_user values( username )这是最典型的低分代码。我用PreparedStatement和MD5重写一遍注册的DAO方法package com.housekeep.dao; import com.housekeep.entity.User; import com.housekeep.util.DBUtil; import java.security.MessageDigest; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; public class UserDao { public boolean register(User user) throws Exception { String sql INSERT INTO t_user(username, password, real_name, phone, address) VALUES(?,?,?,?,?); try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, user.getUsername()); ps.setString(2, md5(user.getPassword())); ps.setString(3, user.getRealName()); ps.setString(4, user.getPhone()); ps.setString(5, user.getAddress()); return ps.executeUpdate() 0; } } public User findByUsername(String username) throws Exception { String sql SELECT * FROM t_user WHERE username ?; try (Connection conn DBUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, username); try (ResultSet rs ps.executeQuery()) { if (rs.next()) { User u new User(); u.setId(rs.getInt(id)); u.setUsername(rs.getString(username)); u.setPassword(rs.getString(password)); u.setRealName(rs.getString(real_name)); u.setPhone(rs.getString(phone)); u.setAddress(rs.getString(address)); u.setAvatar(rs.getString(avatar)); u.setRole(rs.getInt(role)); return u; } } } return null; } public static String md5(String raw) throws Exception { MessageDigest md MessageDigest.getInstance(MD5); byte[] digest md.digest(raw.getBytes(UTF-8)); StringBuilder sb new StringBuilder(); for (byte b : digest) { sb.append(String.format(%02x, b)); } return sb.toString(); } }参数化查询的好处是用户无论输入什么内容都会被当作字符串值而不是SQL语句的一部分这是防注入的标准做法。MD5在这里够用但如果这个系统真要上线至少要做加盐处理或改用BCryptMD5在碰撞攻击面前已经不安全了。登录时先findByUsername查出用户再比对md5(输入密码)是否等于库里存的password而不是把查询条件直接拼进SQL里这样即使密码错误也能区分是用户不存在还是密码不对。4.2 登录拦截与Session管理Filter统一校验超时时间按需调登录成功后的核心操作是把User对象放进session然后区分角色跳转。用户登录跳首页管理员登录跳后台。我这里用一个LoginFilter统一拦截未登录访问代码量不大但覆盖所有需要权限的页面package com.housekeep.util; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String path request.getRequestURI(); if (path.contains(/login.jsp) || path.endsWith(.css) || path.contains(/LoginServlet) || path.contains(/RegisterServlet)) { chain.doFilter(req, resp); return; } HttpSession session request.getSession(false); if (session null || session.getAttribute(user) null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, resp); } }HttpSession对象里不要放太多东西一个user对象加一个可能需要的cart或临时标记就够了。Session默认超时时间在Tomcat里是30分钟课设演示时经常出现刚登录完填个表单就过期跳回登录页的情况可以在web.xml里主动调长session-config session-timeout60/session-timeout /session-config注意Filter里用request.getSession(false)而不是getSession()因为后者在session不存在时会自动创建导致拦截器永远拦截不到未登录状态。用false的话session为空就说明没登录了逻辑才正确。web.xml里还需要注册Filter配置filter-name和url-pattern为/servlet/*和/user/*别漏了第二个。4.3 预约下单用状态机管理订单价格永远以服务端为准下单模块是家政网的业务核心。页面流程是用户选择服务类别和服务人员填写上门时间和地址提交后生成订单并跳转模拟支付页。这里有个安全性细节容易被忽略前端隐藏域传过来的价格后端一定不能直接信。正确做法是根据categoryId从数据库重新查base_price服务次数按小时算的话还要校验服务时长防止用户手工改表单里的价格字段。订单编号的生成用时间戳加三位随机数即可System.currentTimeMillis()拿到19位数字拼接后就是天然唯一的字符串。订单状态机单独抽一个常量类package com.housekeep.entity; public class OrderStatus { public static final int PENDING_PAY 0; // 待支付 public static final int PENDING_SERVICE 1; // 待服务 public static final int SERVING 2; // 服务中 public static final int FINISHED 3; // 已完成 public static final int CANCELLED 4; // 已取消 public static final int REFUNDED 5; // 已退款 }状态流转我建议只在Service层做不允许在Servlet里直接setStatus这样所有状态变化都走同一套校验规则。比如取消订单时只有status等于0或1的时候才允许取消如果订单已经是SERVING状态取消操作要抛业务异常。代码里多写几个if判断不丢人丢了状态控制才是答辩时被抓住问到底的点。4.4 个人信息展示页面图片坐标定位在JSP里的真实玩法jsp个人信息展示页面是检索这个词的同学最常见的刚需。这个页面要展示头像、用户名、真实姓名、手机号、地址和历史订单列表。头像展示有一个路径坑数据库中存的是相对路径upload/avatar.jpg页面里必须用${pageContext.request.contextPath}拼接成完整的上下文路径否则在非根路径部署时图片会404。完整写法是img src${pageContext.request.contextPath}/${sessionScope.user.avatar} stylewidth:80px;height:80px;border-radius:50%; alt头像jsp图片如何对坐标定位这个热搜词其实有两种理解。一种是CSS定位比如给头像右下角加一个会员徽标做法是父容器设置position:relative徽标图片设置position:absolute和left/top像素偏移另一种是HTML的map标签配合usemap做图片热点区域比如在服务区域图上划分几个可点击的区块点击跳转对应区域的分类列表。JSP本身不参与任何定位计算它只负责把图片路径和服务器的动态数据渲染到src属性里。如果是想做地图上的精确坐标老实说应该用百度地图或高德的JavaScript APIJSP里做这个属于自己给自己找麻烦。4.5 页面加载刷新与饿了么Element图标两个前端细节的正确打开方式检索jsp页面让加载完后刷新一次通常发生在两种场景上传完新头像后或者订单状态在另一个页面被修改后。实现方式是在body onloadwindow.location.reload()里调用刷新或者用一个隐藏iframe提交表单、成功后调用parent.location.reload()。但必须加防死循环标记刷新后的URL会带一个参数?reloaded1判断这个参数存在就不再调用reload否则页面会一直刷到浏览器崩溃。再说到饿了么elment图标前端jsp这个搜索词问题本质是Element UI是Vue的组件库JSP页面无法直接实例化el-icon这样的Vue组件。可行做法是去Element UI的GitHub Release页把fonts/目录和对应的index.css下载下来放到WebContent的css和fonts目录里然后通过link标签引入再直接用i classel-icon-user这样的字形图标。但你要明白图标字形可以拿来用el-button那些带交互行为的组件在JSP里是模拟不出来的最多是样式接近。课设阶段老老实实用Bootstrap加Font Awesome比硬套Element UI省心得多。5. 避坑指南我在JSP家政网上踩过的6个翻车现场5.1 表单提交后中文全部变成问号现象注册页面填入张三提交到Servlet后在控制台打印出来是???再存进数据库也是中文乱码。原因POST请求的编码默认是ISO-8859-1Tomcat接收请求时没有按UTF-8解码另外如果数据库表字段的字符集不是utf8mb4存储时也会二次转码失败。解决在web.xml里配置一个编码过滤器或者直接在Servlet第一行写request.setCharacterEncoding(UTF-8)。但最可靠的做法是用CharacterEncodingFilter统一处理注意这个Filter的执行顺序必须排在LoginFilter之前否则登录接口本身也是乱码用户名密码永远验证不过。同时检查MySQ连接的jdbcUrl里带不带characterEncodingutf8不带的话即使请求编码对了写库时仍可能乱码。5.2 提交表单后404或者跳转到带项目名的错误路径现象点击登录按钮后浏览器地址变成了http://localhost:8080/login.jsp页面直接404因为Servlet的映射路径没拼上项目上下文。原因JSP表单里的action写成了绝对路径/LoginServlet而部署后的应用在Tomcat下实际路径是/housekeep/LoginServlet前面少了项目名。另一个常见原因是把response.sendRedirect写成了forward或者反过来导致地址栏路径和实际资源路径不匹配。解决所有跳转统一使用绝对上下文路径request.getContextPath() /LoginServlet。JSP页面里写成${pageContext.request.contextPath}/LoginServletHTML的form标签里也这么拼。这个坑最隐蔽的地方在于IDE里Run on Server时Tomcat有时用根路径部署你本地测着没事换台机器或用war包部署就全部404根因就是路径写死了。5.3 图片上传成功但页面刷新后依然显示旧图或404现象个人中心上传新头像上传提示成功JSP页面刷新后看到的还是老头像或者直接裂图。原因文件确实写到了磁盘但写的是IDE的临时发布目录不是项目源码目录。Eclipse的WebContent会复制到wtpwebapps目录下IDEA会复制到target/classes你在IDE里改的文件没同步过去。更隐蔽的是数据库里存的路径还是旧值上传逻辑只写了文件没更新user表的avatar字段。解决上传时把文件写到CommonConstants里配置的绝对路径比如D:/upload/然后数据库存upload/xxx.jpg再在Tomcat的server.xml里配置一个虚拟目录映射把/upload/**映射到D:/upload/。这样文件与项目解耦不再受IDE重部署影响。上传完成后必须执行new File(oldPath).delete()删掉旧头像不然每次上传都会堆积垃圾文件。5.4 Tomcat启动正常但访问时报ClassNotFoundException或SSL连接错误现象启动Tomcat没问题一访问数据库相关页面就抛java.lang.ClassNotFoundException: com.mysql.jdbc.Driver或者控制台报Could not create connection to database server。原因MySQL 8.0的驱动类名是com.mysql.cj.jdbc.Driver老代码里写的com.mysql.jdbc.Driver在驱动jar升级后已经废弃类加载直接失败。另一个高频原因是MySQL 8默认启用SSLJDBC连接时没加useSSLfalse参数连接过程被TLS握手卡住。解决驱动jar包对应版本选择MySQL 5.7用mysql-connector-java-5.1.49.jarMySQL 8.0用mysql-connector-java-8.0.x.jar。jdbcUrl统一写jdbc:mysql://localhost:3306/housekeep?useSSLfalseserverTimezoneAsia/Shanghai。URL里的时区参数不能省MySQL 8的驱动对时区敏感不指定会报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。还有个边角坑jar包不要同时放在Tomcat的lib目录和项目的WEB-INF/lib目录这会导致ClassLoader加载到两个版本的类偶发异常很难查。5.5 JSP页面无限刷新停不下来浏览器直接卡死现象给body加了onloadlocation.reload()实现加载完后刷新一次的效果结果页面不停刷新CPU占用飙升。原因每次reload后页面重新加载onload事件再次触发形成了死循环。这是jsp页面让加载完后刷新一次这个需求最容易踩的坑核心问题是刷新动作没有终止条件。解决用查询参数做标记。第一次加载时URL不带参数执行reload并拼上?refreshed1第二次加载时页面判断request.getParameter(refreshed)不为空就跳过reload。还有一种方式是session里放一个布尔标记刷新一次后置为false避免URL难看。如果这个刷新的目的是拉取订单状态更优雅的做法是JSP里放一个自动刷新的meta标签然后配合后台接口轮询而不是整页刷新。5.6 用户表role字段设计成String导致权限判断永远不相等现象登录成功后管理员跳转后台时报错或者后台页面明明写死了if(user.role 2)却始终进不来。原因role字段在数据库里是varchar类型存的是2Java里从ResultSet用getInt取值时虽然能自动转成数字但如果用getString取值再和整数比较永远false。另一种情况是页面里用了${user.role 2}EL表达式里整数比较没问题但硬编码2这个魔法数后面前端改了显示逻辑就会漏改。解决表结构里role用TINYINT实体类用Integer比较时统一用OrderStatus那样的常量类做命名引用。数据库里不要存admin这种字符串角色因为字符串没有长度约束容易拼错而且比较效率低。如果已经用了varcharDAO层取值时用rs.getInt(role)强制转换页面端判断顺手加上 的空字符串处理避免与NULL比较时EL表达式返回空。6. 验收与进阶从答辩过关到把它变成加分项的最后一步拿到一个能做、能跑的在线家政网并不等于做完。我习惯按角色走一遍全流程来验收先注册一个普通用户下单等支付再注册一个服务人员账号接单最后用管理员账号在后台看到订单并标记完成。这六个状态节点全部走通项目才算闭环。验收时还要做两个破坏性测试一个是重启Tomcat后数据还在不在另一个是退出登录后直接敲入订单管理页的URL看Filter能不能把你踢回登录页。这两条过了答辩演示就不会掉链子。进阶方向上性价比最高的是给后台管理加一张统计页用JSP显示每日订单数和营收总额数据源就是刚才的t_order表一条SQL的事但演示效果立刻不一样。再往上值得做的是把DAO层从JDBC换成MyBatis实体类和Service层基本不动这是答辩被问到你觉得哪里可以改进时最标准也最好讲的答案——因为你有旧代码做对比能说出具体差异。最后说一个我的习惯做法数据库建表时就把状态字段的注释写清楚Java里对应的常量类同步建好再写业务代码。状态机想清楚了后面所有业务代码都是线性往下写不用回头改。这套JSP家政网方案做成什么深度取决于你想让它过还是一个能讲的完整项目。选后者的话哪怕技术栈旧把业务闭环和权限边界做扎实了一样是能拿得出手的东西。希望帮到你。本文还有配套的精品资源点击获取
返回列表