ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

基于JSP+Servlet+MySQL的家具电商销售系统设计与实现

基于JSP+Servlet+MySQL的家具电商销售系统设计与实现 简介一份聚焦网上家具销售系统设计与实现的毕业设计论文文档适合计算机专业学生、准备毕设的开发者及希望学习JSPJAVAMySQL技术栈的初学者。资源围绕家具电商平台展开涵盖项目背景、需求分析、系统设计目标及完整功能模块包括个人中心、首页轮播、家具资讯、客户审核、家具分类、家具审核、卖家审核、售后维权和统计中心等从买家、卖家与管理端展示系统构建思路。压缩包共1个doc文件大小1.66MB内容层次分明既可作为毕业设计论文写作参考也能用于课程项目开发实战。目前已吸引50人学习说明其对同类选题具备一定借鉴价值。读者可通过该文档掌握从需求梳理、技术选型到功能落地的完整流程理解JSP动态网页技术、Java后端开发与MySQL数据库的实际应用同时学习项目管理与团队协作要点为独立完成类似Web系统开发打下扎实基础。1. 从二手家具交易说起为什么需要一套JSP销售系统家具是大件低频商品线下比价要跑好几个卖场物流和搬运成本又高二手家具的交易就更麻烦了。我做这套网上家具用品销售系统时核心目标是让买家能一直逛、随时下单卖家能自助上架商品管理员只做审核和数据维护而不是替所有角色做手工操作。整个系统基于JSPServletMySQL实现部署在Tomcat上业务上覆盖了从注册、浏览、购物车、下单到售后维权的完整闭环也正好覆盖本科毕业设计里常见的电商选题。对于正在准备毕业论文或课程项目的开发者来说这个项目最有价值的地方不在于功能多炫而在于它把用户角色权限、商品状态流转、订单生命周期这些电商通用逻辑落到了一个可以逐行读完的中等规模代码库里。接下来的内容会按技术选型、数据库设计、核心模块实现、部署测试的顺序拆开讲每一步都有可以照着写的代码和参数说明。2. JSP、Servlet与MySQL这套技术栈为什么还没过时2.1 B/S架构下的角色边界系统采用B/SBrowser/Server结构浏览器只负责渲染和提交请求所有业务逻辑集中在服务器端。这样做的好处是客户端零安装学校机房、老旧PC都能直接访问而且后续功能升级只动服务端代码即可。系统里实际有三类角色买家普通注册会员、卖家审核通过后可发布家具、管理员负责审核和统计。角色不同能访问的菜单和操作按钮也不同这个权限控制放在Servlet的过滤器中统一处理。具体做法是在web.xml里配置一个Filter拦截所有/admin/*和/seller/*路径的请求从session中取出当前登录用户判断角色是否匹配public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; HttpSession session request.getSession(false); User user session null ? null : (User) session.getAttribute(loginUser); if (user null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } String uri request.getRequestURI(); if (uri.startsWith(/admin/) user.getRole() ! 1) { response.sendError(403); return; } if (uri.startsWith(/seller/) user.getRole() ! 2) { response.sendError(403); return; } chain.doFilter(req, resp); }这段代码里的核心判断有两处会话过期检查先做避免空指针角色判断按角色值硬编码的role字段用1表示管理员、2表示卖家、0表示普通买家这种设计在小型系统里很简单直接比引入Shiro或Spring Security轻量得多。2.2 JSP页面与Servlet的分工逻辑JSP的本质是一个被容器翻译成Servlet的模板文件第一次访问时会经过翻译、编译、加载、实例化四个阶段。在JSP中直接写业务代码虽然方便但会带来两个问题页面里塞满% ... %脚本段后前端难维护业务逻辑散落在各个JSP中排查问题时无法集中定位。实际开发中我采用的约定是JSP只负责展示数据和提交表单所有请求先发给ServletServlet调用DAO层访问MySQL然后把结果放回request或session最后forward或redirect到目标页面。京东商品详情页的请求路径设计是/furniture/detail?id10对应的Servlet先按id从数据库查出家具详情再查出该卖家的其他在售商品用于关联推荐一起放进request域后转发到detail.jsp。JSP页面里用${furniture.name}和${sellerList}这样的EL表达式取值页面中除了c:forEach标签不出现任何Java代码。2.3 为什么选MySQL而不是SQL Server论文初稿里写的是SQL Server 2005但实际开发时我更倾向MySQL 5.7。原因有几点MySQL体积小解压版不到200MB学生机上跑得动JDBC驱动是com.mysql.jdbc.Driver连接字符串写法简单MySQL的InnoDB引擎默认支持事务正好满足订单表需要原子操作的场景。另外一个不可忽视的因素是后期如果想把项目部署到Linux服务器上演示MySQL的跨平台迁移比SQL Server顺畅得多。对比维度MySQL 5.7SQL Server 2005跨平台Windows / Linux / macOS仅 Windows默认存储引擎InnoDB支持事务无独立引擎概念JDBC驱动com.mysql.jdbc.Drivercom.microsoft.sqlserver.jdbc.SQLServerDriver获取成本开源免费商业授权如果只是想跑通代码MySQL就够了。如果论文里需要对比数据库选型可以补一句SQL Server在Windows环境的维护成本更高、周边工具更重不与项目规模匹配。3. 数据库设计从需求到建表SQL3.1 核心实体识别系统涉及的核心实体可以归纳为六类用户含买家/卖家/管理员三种身份、家具商品、家具分类、订单与订单明细、轮播图片、售后维权记录。实体之间的关系是一对多为主一个分类下有多个家具一个订单包含多个订单明细一个会员可以发起多次售后申请。角色统一存放在用户表用role字段区分不做三张独立的表。原因是注册入口唯一、登录逻辑相同拆开反而增加跨表查询的复杂度。家具商品也必须归属某个审核通过的卖家商品发布时从session中取当前用户id作为sellerId不允许前端传该字段这一步能防止水平越权。3.2 数据表结构详解下面给出四张核心表的建表SQL覆盖了买家、商品、订单三条最关键的链路CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, nick_name VARCHAR(50), role TINYINT NOT NULL DEFAULT 0 COMMENT 0买家 1管理员 2卖家, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待审核 1正常 2禁用, phone VARCHAR(20), create_time DATETIME DEFAULT CURRENT_TIMESTAMP ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_furniture ( id INT PRIMARY KEY AUTO_INCREMENT, seller_id INT NOT NULL, category_id INT NOT NULL, title VARCHAR(100) NOT NULL, description TEXT, price DECIMAL(10,2) NOT NULL, cover_img VARCHAR(255), status TINYINT NOT NULL DEFAULT 0 COMMENT 0待审核 1在售 2下架 3拒绝, view_count INT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_seller (seller_id), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_cart_item ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, furniture_id INT NOT NULL, quantity INT NOT NULL DEFAULT 1, add_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_furniture (user_id, furniture_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_order ( id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL UNIQUE, user_id INT NOT NULL, total_amount DECIMAL(10,2) NOT NULL, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待付款 1已付款 2已发货 3已完成 4已取消, receiver_name VARCHAR(50) NOT NULL, receiver_phone VARCHAR(20) NOT NULL, receiver_address VARCHAR(255) NOT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, KEY idx_user (user_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; CREATE TABLE t_order_item ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL, furniture_id INT NOT NULL, furniture_title VARCHAR(100) NOT NULL, price DECIMAL(10,2) NOT NULL, quantity INT NOT NULL, KEY idx_order (order_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;字段注释里已经把状态值标出来了这里特别说明几个容易踩坑的点。购物车表使用user_id furniture_id做联合唯一键用户重复点击“加入购物车”时执行ON DUPLICATE KEY UPDATE quantity quantity 1避免出现同一商品两行记录。订单表冗余了furniture_title和price字段这样做的好处是卖家把商品改价或删除后订单详情页依然能显示下单时的原始快照不需要做复杂的连表查询。order_no在设计上建议用yyyyMMddHHmmss 用户id后四位 随机数拼装保证并发环境下不会撞号。3.3 索引与事务设计要点统计中心涉及按分类汇总销量、按月统计订单金额这两类查询如果数据量涨到几万条全表扫描会明显变慢。建议在t_order_item的furniture_id上建普通索引在t_order的create_time上建索引覆盖统计模块的WHERE条件即可。事务方面下单操作需要同时向t_order和t_order_item写数据必须放在同一个事务里用Connection.setAutoCommit(false)开启提交成功后调用commit()任一步异常则rollback()并把连接归还连接池。需要说明的是库存扣减这里用UPDATE t_furniture SET stock stock - ? WHERE id ? AND stock ?的原子更新方式而不是先SELECT再UPDATE可以避免超卖问题。4. 核心模块实现从购物车到售后维权4.1 购物车的设计与请求流转购物车数据不存数据库临时表而是直接存在session中。实现方式是定义一个Cart实体类内部持有一个MapInteger, CartItemkey为家具id。添加商品时先从session中取出Cart对象如果为null则new一个放进去执行添加操作后再把Cart放回session。这种设计的优点是用户没登录也能加购登录后数据也不会丢session不过期的话。缺点是换浏览器或清缓存后购物车清空但作为课程设计级别够用。public class Cart { private MapInteger, CartItem items new HashMap(); public void addItem(HttpServletRequest request, Furniture furniture, int quantity) { CartItem item items.get(furniture.getId()); if (item null) { item new CartItem(furniture, 0); items.put(furniture.getId(), item); } item.setQuantity(item.getQuantity() quantity); request.getSession().setAttribute(cart, this); } public void updateQuantity(int furnitureId, int quantity) { CartItem item items.get(furnitureId); if (item ! null) { if (quantity 0) { items.remove(furnitureId); } else { item.setQuantity(quantity); } } } public double getTotalPrice() { double total 0; for (CartItem item : items.values()) { total item.getFurniture().getPrice() * item.getQuantity(); } return total; } }这段代码的关键点是CartItem中持有Furniture对象而不是仅在Map里存id加数量这样购物车页面渲染商品名称、单价、封面图时不需要再查数据库减少了一次IO。getTotalPrice方法在结算页和购物车列表页都会被调用金额在提交订单时以数据库查询出的最新价格为准不能信任购物车中缓存的价格避免卖家改价后订单金额不一致。4.2 家具审核流卖家上架与管理员把关家具上架后不能立即在前台展示需要管理员在后台审核。审核逻辑涉及两张表的状态同步t_furniture.status控制商品展示状态t_user.status控制卖家账户状态。新注册的卖家默认是待审核状态此时t_furniture的status字段会被置为2下架前台查询列表时用WHERE status 1过滤待审核商品只有管理员的待审列表里才能看到。审核操作在FurnitureServlet中实现管理员点击“通过”时执行以下逻辑public void auditFurniture(int furnitureId, int auditResult, String reason) { String sql UPDATE t_furniture SET status ? WHERE id ?; // auditResult: 1 通过, 3 拒绝 jdbcTemplate.update(sql, auditResult 1 ? 1 : 3, furnitureId); if (auditResult 3) { String reasonSql INSERT INTO t_audit_log (furniture_id, reason, audit_time) VALUES (?, ?, NOW()); jdbcTemplate.update(reasonSql, furnitureId, reason); } }拒绝时不直接删除商品而是写一条审核日志存下原因买家端拉取该商品的详情接口时返回status3和原因字符串卖家在“我的商品”列表里能看到被拒的具体原因并修改后重新提交。审核流能对上论文里的“客户审核管理”和“家具审核管理”两个功能点且状态流转清晰。4.3 订单生命周期与售后维权订单状态从待付款到已完成一共五个节点状态变更全部通过FrontOrderServlet控制。买家提交订单时系统生成订单号、从购物车清单组装订单明细、计算总金额、清空购物车这三步必须在一个事务里完成。支付环节在原论文中设计了两种方式货到付款和在线支付。作为演示系统在线支付可以用一个假接口替代点击“立即支付”时直接更新订单状态为已付款而不对接真实支付宝或微信支付网关。售后维权单的设计比较关键它的核心是关联订单。买家在“我的订单”中点击“申请售后”时需要提交原因和说明还要选择是退款还是退货退款CREATE TABLE t_after_sale ( id INT PRIMARY KEY AUTO_INCREMENT, order_id INT NOT NULL, user_id INT NOT NULL, furniture_id INT NOT NULL, type TINYINT NOT NULL COMMENT 1退款 2退货退款, reason VARCHAR(255) NOT NULL, status TINYINT NOT NULL DEFAULT 0 COMMENT 0待审核 1同意 2拒绝, apply_time DATETIME DEFAULT CURRENT_TIMESTAMP, handle_time DATETIME, handle_note VARCHAR(255) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;申请表插入成功后需要同步把对应订单的status置为5维权中原论文中未定义这里额外扩展一个状态。这样做是把售后处理也纳入订单状态机管理管理员在后台通过/拒绝售后单时再做一次状态回写同意则订单变更为已完成拒绝则恢复为已发货。5. 部署、测试与统计分析的落地技巧5.1 Tomcat部署Web项目的两种方式把项目部署到Tomcat上有两种常见方式。第一种是把整个Web项目打war包放到webapps目录下启动时Tomcat自动解压第二种是在conf/server.xml的Host节点中配置虚拟目录用Context path/furniture docBaseD:/project/furniture-web /映射到项目根目录。开发阶段我习惯用第二种改完JSP直接刷新浏览器就能看到效果不用重启容器。需要注意一个问题如果JSP页面中包含中文字符web.xml里必须声明页面编码过滤器否则Tomcat默认用ISO-8859-1解析POST请求参数会出现中文乱码。这个过滤器的encoding参数设为UTF-8forceEncoding设为true放在所有Servlet映射之前。filter filter-nameencodingFilter/filter-name filter-classorg.apache.catalina.filters.SetCharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mapping5.2 测试的重点状态流转和权限边界功能测试不能只走“注册、登录、下单”这条快乐路径。建议按角色分场景测普通买家访问/admin/list.jsp应该被过滤器拦下返回403未登录用户直接访问购物车页面应该被重定向到登录页卖家修改商品的接口要校验当前用户id是否等于t_furniture.seller_id否则就是越权操作。这些用例在测试报告里列成表格比单纯写“功能正常”更有说服力。另外可以在浏览器的开发者工具里看请求响应时间如果首页轮播图和商品列表图片加载慢优先检查图片是否没有压缩。原系统的存量图片可以直接放在webapps/upload目录下图片尺寸统一限制在800px以内用Photoshop或开源工具批量压一下再传页面加载速度能提升一个量级。5.3 统计中心的SQL实现统计中心要实现三个指标家具销售量排行、分类占比、近七天订单趋势。核心SQL如下CREATE VIEW v_furniture_sales AS SELECT f.id, f.title, f.price, COALESCE(SUM(oi.quantity), 0) AS total_sales FROM t_furniture f LEFT JOIN t_order_item oi ON f.id oi.furniture_id LEFT JOIN t_order o ON oi.order_id o.id AND o.status IN (1, 2, 3) GROUP BY f.id, f.title, f.price ORDER BY total_sales DESC;这里把SUM(oi.quantity)做了空值兜底因为新上架还没形成订单的商品在左连接中会得到NULL直接显示0而不是空白更友好。状态条件限定在已付款、已发货、已完成三种排除了已取消和待付款的订单数据保证统计口径准确。近七天订单趋势直接对t_order.create_time按日期分组用DATE_FORMAT(create_time, %Y-%m-%d)做分组键。如果论文的测试部分需要截图建议把统计页面的柱状图用JFreeChart或者直接在JSP页面用Chart.js的CDN方案画折线图。前端页面用Chart.js只需引入一个js文件后端Servlet把查询结果转成JSON输出到页面图表就能渲染出来比服务端绘图少很多麻烦。本文还有配套的精品资源点击获取
返回列表