ARTICLE DETAIL

资讯详情

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

JavaWeb购物商城实战:Servlet+Tomcat+MySQL从开发到部署

JavaWeb购物商城实战:Servlet+Tomcat+MySQL从开发到部署 简介这是一份面向JavaWeb初学者的购物商城项目基于JSPServletMySQL实现覆盖用户注册登录、商品浏览、购物车管理、订单提交与管理员后台等完整电商流程适合用来理解MVC分层、DAO模式以及会话与请求处理。压缩包共270个文件包含31个Java源码、9个JSP页面、21个XML配置、10个CSS样式、6个JS脚本、10个Jar依赖库以及SQL/DB数据库脚本整体仅7.08MB属于轻量级教学项目。目前已吸引1285人学习下载。包内类文件如CommodityAction、CommodityDAOImpl、AddToCarAction等清晰展示了从控制器、业务层到数据访问层的代码组织方式便于对照学习商品添加、分类展示、购物车和订单生成等核心逻辑。对于正在做课程设计或想快速上手JavaWeb开发的同学这份资源能提供可直接运行的工程骨架和数据库表结构参考。1. 为什么是“JavaWeb购物商城”1.1 这个项目到底能练什么先说个实情。做了这么多年Java后端我见过太多简历上写着“仿淘宝商城”“xx购物系统”的应届生结果一问购物车怎么实现答不上来。但反过来我也见过真把一个JavaWeb购物商城从头到尾写完的人他对Servlet生命周期、HttpSession、数据库事务、Tomcat部署这套东西的理解比很多背了两年八股文的同学扎实太多。原因很简单。购物商城这个项目功能链路完整难度梯度合理几乎覆盖了JavaWeb阶段所有核心知识点前端页面交互、Servlet控制层、Service业务层、DAO数据访问层、数据库表设计、会话管理、文件上传下载商品图片、订单状态流转、事务控制。从用户注册登录到浏览商品、加购、结算、下单、支付模拟再到后台的订单管理、商品管理做完这一套等你再去看Spring Boot、MyBatis这些框架就会产生一种“原来框架解决的是这些问题”的通透感。这不是过度神化一个练手项目而是因为商城的业务逻辑足够自然每个环节都能逼你思考“为什么”。所以这篇文章不打算给你贴一大段完整代码然后说“拿去跑”那没有意义。我想认真拆一遍从IDEA 2023版本创建JavaWeb项目开始到数据库设计、核心流程实现、最后在Windows Server上用Apache Tomcat把项目发布出去。中间穿插我实际踩过的坑和优化习惯希望你看完能自己动手把项目从0到1搭起来。1.2 技术选型别一上来就Spring Boot我知道现在很多人一听到JavaWeb就直接上Spring Boot这没有错。但如果你的目标是吃透JavaWeb的基础链路我强烈建议第一个商城项目用纯Servlet JSP MySQL Tomcat来做。原因有两个。第一Spring Boot帮你屏蔽了太多东西。内嵌Tomcat、自动配置、依赖管理你写一个RestController就能返回JSON但底层Servlet是怎么被容器调起来的请求是怎么从浏览器走到你方法里的Session是怎么维持的这些东西在Spring Boot里几乎透明出了问题你根本无从下手。纯Servlet项目里你手动配置web.xml、自己写HttpServlet子类、自己管理HttpSession虽然繁琐但每一步都是透明可控的这对基本功的打磨非常关键。第二纯Servlet写一遍你会对“框架到底做了什么”有更深的敬意。我见过一个同事用Spring Boot很溜但遇到一个诡异的Bug请求参数中文乱码。他折腾了半天没找到原因最后发现是因为Spring Boot默认的字符编码过滤器没生效。而如果你在Servlet阶段手动配置过CharacterEncodingFilter这个东西在你脑子里是有记忆的。所以技术选型这件事不要只看热度要看你想获得什么。具体版本方面我建议JDK 1.8或11别用17纯Servlet阶段没必要给自己找模块化的麻烦Tomcat 9.x对应Servlet 4.0规范MySQL 5.7或8.0都可以IDE用IDEA 2023版本Maven管理依赖。这个组合是我实际跑过很多遍的稳定、资料多、报错都能搜到。2. 环境准备IDEA 2023创建JavaWeb项目的正确姿势2.1 从新建Maven项目到跑通第一个ServletIDEA 2023版本创建JavaWeb项目比老版本简单了不少但很多第一次接触的人还是会懵。我习惯的方式是新建一个Maven项目不急着勾选“Web Application”模板而是先把项目骨架建好再手动添加Web目录结构。这样对每一个文件的作用心里都有数。具体步骤大概是这样打开IDEA选择New Project左侧选择MavenJDK选1.8或11不要勾选模板直接Next。填好groupId一般是域名倒写如com.example、artifactId项目名如shop、version保持默认。项目创建后在src/main目录下手动创建webapp目录并在webapp下创建WEB-INF文件夹。在WEB-INF下创建web.xml文件这个文件是JavaWeb项目的部署描述符Servlet的路由映射、过滤器配置都在里面。在pom.xml里加上Servlet API的依赖javax.servlet:javax.servlet-api:4.0.1scope设为provided因为Tomcat自带、JSP依赖javax.servlet.jsp:javax.servlet.jsp-api:2.3.3同样provided、MySQL驱动mysql:mysql-connector-java:8.0.33、JSTL标签库javax.servlet:jstl:1.2以及数据库连接池推荐commons-dbcp2或c3p0。配置Tomcat进入Run - Edit Configurations点号选择Tomcat Server - Local在Application server里选择你本地解压好的Tomcat路径。在Deployment标签页点选择Artifact选中项目的war exploded包Application context填/shop。搞定这些后先别急着写业务代码。写一个最简单的HelloServlet继承HttpServlet重写doGet和doPost方法在web.xml里注册路由或者用Servlet 3.0的WebServlet注解IDEA 2023版本创建的Maven项目默认支持Java EE规范可以直接用注解启动Tomcat访问http://localhost:8080/shop/hello看到页面输出说明环境通了。这一步跑通了整个项目的地基就算打好了。后面所有的业务都是在这个框架上往上垒。2.2 环境里最容易翻车的三个点环境配置阶段我每次带人都会强调几个高发问题提前说明白能少走很多弯路。第一是IDEA中的Tomcat配置里On Update action和On frame deactivation这两个选项建议分别设为Redeploy和Update classes and resources。否则你改一个JSP页面Tomcat不热更新每次都要重启特别耽误事。但注意改Java代码还是建议重启热部署偶尔会出状态错乱的毛病。第二是provided作用域的问题。Servlet API和JSP API的依赖作用域必须是provided意思是编译时需要但打包和运行时交给Tomcat提供避免把javax.servlet.jar打包进WAR包和Tomcat自带的冲突。这个错误很经典症状是启动时出现java.lang.LinkageError或者ClassNotFoundException排查半天最后发现是依赖冲突。第三是MySQL驱动的版本坑。如果你用MySQL 8.0驱动类名要写成com.mysql.cj.jdbc.Driver不是com.mysql.jdbc.Driver后者已被废弃。同时连接URL必须带上serverTimezoneAsia/Shanghai这种时区参数否则会报The server time zone value Öйú±ê׼ʱ¼ä is unrecognized。这个问题在数据库版本升级后特别容易遇到建议直接把驱动版本和时区配置写进自己的模板里每次新建项目直接套用。3. 数据库设计与核心功能拆解3.1 购物商城的核心表其实就这几张商城项目的数据表网上能找到很多复杂的几十张表的设计方案但第一版做出来真正核心的就五张用户表t_user、分类表t_category、商品表t_product、购物车表t_cart_item、订单表t_order订单明细表t_order_item。订单和订单明细是一对多关系必须拆开。我实际用过的表结构简单说一下你可以直接参考t_userid主键自增、username唯一、password记得存MD5或加盐哈希别存明文、phone、email、create_time。t_categoryid、name、sort排序号控制前台展示顺序、create_time。分类一般做一级就够了商城练手项目做多级分类是给自己找事。t_productid、category_id外键关联分类表、name、subtitle副标题/卖点描述、main_image主图URL、sub_images轮播图多个路径用逗号拼接、price用decimal(10,2)、stock库存用int、status状态1在售0下架、create_time、update_time。t_cart_itemid、user_id、product_id、quantity、checked是否选中这个字段在做批量结算时很有用唯一索引建议加(user_id, product_id)保证一个用户对同一商品只有一条购物车记录。t_orderid、order_no订单号建议用时间戳随机数生成别用自增id当订单号、user_id、total_price、status状态机0待付款、1待发货、2待收货、3已完成、4已取消、receiver_name、receiver_phone、receiver_address、create_time、pay_time、send_time、close_time。t_order_itemid、order_id、product_id、product_name快照字段防止商品改名后订单显示错乱、product_image、current_unit_price下单时的价格快照、quantity、total_price。这里的关键设计思路是“快照”。订单明细里的商品名称和价格必须保存下单那一刻的数据不能通过关联商品表实时查。否则你下单后商品降价订单里的价格跟着变会出大乱子。这在实际电商系统里是基本要求练手阶段就要养成这个习惯。3.2 登录注册与Session管理别把状态搞丢登录注册是商城第一个要做的功能看起来简单但里面全是细节。注册要注意的是用户名唯一性校验别只在页面端做JS校验后端insert之前必须查一遍否则并发重复提交会插入两条相同用户名的记录。正确做法是给username字段加唯一索引然后后端插入时捕获DuplicateKeyException再提示用户“用户名已存在”。数据库层面的兜底比业务代码检查更可靠。密码存储早期很多教程直接MD5(password)现在已经不推荐了至少要加盐。比如MD5(password salt)其中salt可以是用户注册时生成的一串随机字符串。这样就算数据库泄露彩虹表也攻击不了。登录的Session管理是重点。用户登录成功后把用户对象存入HttpSession这个Session是有存活时间的Tomcat默认30分钟无访问就失效。问题来了用户长时间停留在某个页面然后点购物车突然被踢到登录页体验很差。一个常见的优化是购物车这类接口在前端Ajax调用时如果发现401未登录弹个登录框而不是直接跳转整页另外把Session超时时间适当调长或者在用户活跃时自动续期。还有个实际经验不要只把用户id存Session然后把用户状态信息都往Session里塞。因为Session是存在服务器内存里的用户量一大内存会暴涨。练手项目无所谓但养成习惯是好事——Session里只存userId其他用户资料每次请求动态查。3.3 购物车加购与订单结算的流程陷阱购物车和订单结算是整个商城业务逻辑最核心、也最容易写错的地方。购物车加购很多人第一版会习惯性地“先删除老记录再插入新记录”或者“查一下有没有记录有就update没有就insert”。这两种都有问题第一种在高并发下会丢记录第二种虽然逻辑对但语义不清晰。最稳妥的做法是直接用INSERT ... ON DUPLICATE KEY UPDATE quantity quantity 1利用(user_id, product_id)的唯一索引一次性完成“存在则数量加一不存在则插入”的操作。一条SQL搞定性能好还不容易出bug。订单结算的流程就复杂了。从购物车勾选商品点击结算后端要做的事按顺序是校验登录状态、根据购物车记录查出商品最新价格、计算总金额、生成订单号和订单记录、生成订单明细、扣减库存、清空购物车对应记录。这里面最核心的坑是库存扣减。第一版我写过这样的代码查出商品当前库存判断库存是否足够然后UPDATE t_product SET stock stock - ? WHERE id ?。这个逻辑在单用户测试时没问题但两个人同时下单同一件商品就可能超卖。正确做法是加一个条件判断UPDATE t_product SET stock stock - ? WHERE id ? AND stock ?也就是把库存校验和扣减放在同一条SQL里完成靠MySQL的行锁保证原子性。然后检查受影响行数如果为0说明库存不够直接回滚事务提示“库存不足”。另外订单功能一定要开启事务。我的建议是设计一个OrderService.createOrder()方法整个方法用Transaction包裹JDBC阶段可以手动conn.setAutoCommit(false)或者用ThreadLocal包装一个Connection工具类。中间任何一步失败全部回滚否则会出现“订单创建了但库存没扣”或者“库存扣了但购物车还在”的脏数据。4. 项目打包与部署Windows Server Apache Tomcat4.1 打War包、扔进Tomcat的完整过程开发环境下IDEA自带的Tomcat跑得很欢但项目最终是要部署到服务器上的。最常见的方案是打War包扔进Tomcat的webapps目录启动Tomcat自动解压部署。打包方式很简单在IDEA右侧的Maven工具窗口点开Lifecycle双击clean再双击package。Maven会帮你把项目打成War包位置在target目录下文件名一般是shop.war。把这个War包复制到Tomcat的webapps目录下启动Tomcat它会自动解压成一个shop目录访问路径就是http://服务器IP:8080/shop。这里有个小细节War包的解压依赖Java的临时目录权限Windows Server上如果系统临时目录权限不对会解压失败。遇到了别慌检查一下TEMP和TMP环境变量指向的目录有没有写权限。另外生产环境的Tomcat不建议用默认的8080端口暴露在外网。要么改server.xml里的Connector port要么在前面挂一层Apache或Nginx做反向代理把80端口转发到8080。这也是为什么热词里有“Windows Server Apache Tomcat 发布JavaWeb项目”这个组合——因为这个方案在中小企业Windows服务器里真的非常常见。4.2 Apache和Tomcat为什么要配在一起很多新手不理解Tomcat本身就是Web服务器为什么前面还要挂一个Apache这不是多此一举吗直接说结论Tomcat处理动态请求Servlet/JSP很强但处理静态资源图片、CSS、JS、HTML的能力一般而且承受高并发静态访问时性能不如Apache。Apache的优势在于静态文件处理性能高、配置灵活、支持mod_rewrite伪静态。所以典型的架构是Apache监听80端口遇到静态资源请求比如商品图片、CSS、JS自己直接处理遇到动态请求*.jsp、/servlet/*就通过mod_jk或反向代理转发给Tomcat。Windows Server上的配置我推荐用Apache的mod_proxy模块比mod_jk好配很多不用额外装isapi_redirect.dll那一套。核心配置就两段# 加载反向代理模块 LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so # 转发动态请求给Tomcat ProxyPass /shop/ http://localhost:8080/shop/ ProxyPassReverse /shop/ http://localhost:8080/shop/这样配置后用户访问http://你的域名/shop/index.jspApache会原封不动转发给Tomcat处理。如果你还想把静态资源和动态资源分离可以在Apache里对图片、CSS等目录单独配置Alias指向服务器上存放资源文件的路径绕开Tomcat。这个方案的好处是80端口直出用户不用记8080静态资源压力被Apache扛住后续想加负载均衡Apache还能通过mod_proxy_balancer挂多个Tomcat实例。在云服务器上这基本是入门级JavaWeb项目部署的标配。4.3 部署之后90%的人会踩的坑部署完成、页面能访问这只是开始。上线后我遇到过的经典问题挑三个说。第一个是乱码问题。Windows Server上一旦出现中文乱码先查三个地方数据库连接的URL是不是带了characterEncodingutf8页面是不是统一用了UTF-8编码JSP页面pageEncoding、HTML的meta charset、Servlet里的request.setCharacterEncoding(UTF-8)Tomcat的server.xml里Connector有没有配URIEncodingUTF-8。这三个全配齐基本能解决95%的乱码。第二个是端口占用。经常遇到的情况是服务器重启后Tomcat启动失败看日志发现Address already in use: JVM_Bind:8080。八成是你上次Tomcat没有正常关闭进程还挂在后台。Windows Server上可以打开任务管理器把Java进程结束或者用netstat -ano | findstr :8080查到占用进程的PID然后taskkill /F /PID PID。第三个是路径问题。本地开发用的绝对路径一部署全失效。如果在代码里写过C:\Users\xxx\uploads这种硬编码路径到服务器上必炸。项目里所有涉及文件存储的路径都要配置化。我习惯在web.xml里定义一个上下文参数upload.path然后用getServletContext().getInitParameter(upload.path)读取。这样换环境只改配置不改代码。5. 常见问题与排查技巧实录5.1 典型报错速查表下面这个表是我做商城项目这几年整理出来的高频报错和对应的处理办法。建议收藏出了问题先对着查一遍比自己瞎猜快得多。报错信息原因分析解决方法ClassNotFoundException: com.mysql.jdbc.DriverMySQL驱动版本或类名不对MySQL 8.0用com.mysql.cj.jdbc.Driver并确认War包里包含驱动依赖The server time zone value Öйú±ê׼ʱ¼äMySQL连接URL缺少时区参数URL添加serverTimezoneAsia/ShanghaiHTTP Status 404 - /shop/xxxServlet路由配置错误或未部署成功检查web.xml/注解映射、Tomcat部署上下文路径java.lang.LinkageErrorServlet/JSP API重复打入War包依赖作用域设为provided排除运行时冲突Address already in use: JVM_Bind端口被上一次的Java进程占用netstat -ano查PIDtaskkill /F结束进程Cannot load JDBC driver class com.mysql.jdbc.Driver驱动依赖缺失或打包时未包含确认pom.xml有MySQL驱动依赖清理后重新package数据库中文乱码连接URL、页面编码、数据库编码任一处不一致统一UTF-8连接串加characterEncodingutf8库存扣减出现负数并发下没有做原子性扣减用UPDATE ... SET stock stock - ? WHERE id ? AND stock ?用户退出登录后按浏览器后退仍能访问Session失效后浏览器缓存了页面在动态页面加Cache-Control: no-cache响应头或强行校验Session5.2 我的几个独家避坑习惯最后分享几个我个人的习惯不指望所有人都认同但确实帮我省了很多事。第一所有SQL都打日志。JDBC阶段可以用一个简单的SqlUtil工具类把每一条执行的SQL和参数拼出来打印到控制台。别嫌丑排查问题的时候能直接看到“原来是这条SQL不对”比对着报错信息猜半天有效得多。第二数据库和代码结构尽量同步演进。我见过很多人改表结构不加注释过两个月自己都忘了。强烈建议每张表都带上comment说明关键字段也写上备注。这个好习惯等你接手别人的项目时体会更深。第三开发期间不要一次性把功能全写完后才启动测试。每写完一个功能就启动Tomcat验证一次。炒菜讲究“少量多次”写JavaWeb项目更是这样——一次改动太多出问题了连是谁引起的都找不到。第四项目做完后用Maven执行clean package打一个War包在干净的Tomcat目录里重新部署一次。除了验证必须依赖的pom.xml之外还能养成“打包可靠”的习惯。很多人在IDEA里跑得好好的一到部署就抓瞎就是因为从来没有做过冷部署验证。我个人在实际操作中的体会是JavaWeb购物商城这个项目真正的难点不在“写代码”而在于把每个环节都想透彻——为什么这个表要这么设计为什么这段逻辑要加事务为什么部署架构要叠两层服务器。把这些“为什么”搞清楚了哪怕后面不用纯Servlet、换了Spring Boot这些根基上的经验照样能迁移过去。如果你正卡在某个环节不妨把这篇里的速查表打开逐条核对多半能把你从坑里捞出来。本文还有配套的精品资源点击获取
返回列表