当前位置: 首页 > news >正文

JDBC+Servlet+JSP 入门实战

大家好!今天给大家分享一个从零搭建的简易电商后台项目,用到了最基础的 Java Web 技术栈:JDBC 操作数据库、Servlet 处理请求、JSP 渲染页面,全程都是原生实现,没有框架加持,特别适合新手练手,帮你彻底搞懂 Java Web 的底层流程。


一、项目整体架构

先给大家梳理一下整个项目的结构,标准的 Maven Web 项目,分层清晰,方便后续扩展:

mall ├── src │ ├── main │ │ ├── java │ │ │ ├── com │ │ │ │ ├── entity # 实体类(User、Product) │ │ │ │ ├── dao # 数据访问层(数据库操作) │ │ │ │ ├── service # 业务逻辑层 │ │ │ │ ├── servlet # 控制层(处理请求) │ │ │ │ └── util # 工具类(JDBC连接池封装) │ │ ├── resources │ │ └── webapp │ │ └── index.jsp # 前端页面 │ └── test/java # JUnit单元测试类 └── pom.xml # Maven依赖配置

整体遵循经典的MVC 分层架构

  • Entity 层:数据库表对应的实体类,和表字段一一映射
  • DAO 层:直接和数据库交互,封装增删改查操作
  • Service 层:处理业务逻辑,调用 DAO 层方法
  • Servlet 层:接收前端请求,调用 Service 层,转发到 JSP 页面
  • JSP 层:渲染页面,展示数据

二、环境准备与依赖配置

1. Maven 依赖

项目需要用到 JUnit、Servlet、JSTL、Lombok、MySQL 驱动这些核心依赖,直接在pom.xml里配置即可:

<dependencies> <!-- JUnit单元测试 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> <!-- Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- JSTL标签库 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> </dependency> <!-- Lombok简化实体类 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.30</version> <scope>provided</scope> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.49</version> </dependency> </dependencies>

这些依赖覆盖了测试、Web 开发、数据库连接、工具简化等场景,Lombok 的@Data注解能帮我们省去 getter/setter/toString 这些重复代码,非常方便。

2. 数据库创建

先创建电商项目需要的数据库和两张核心表:用户表user和商品表product,SQL 脚本如下:

-- 创建数据库 CREATE DATABASE IF NOT EXISTS mall DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE mall; -- 创建用户表 CREATE TABLE IF NOT EXISTS `user` ( `id` INT AUTO_INCREMENT PRIMARY KEY COMMENT '用户ID,主键自增', `name` VARCHAR(50) NOT NULL COMMENT '用户名', `password` VARCHAR(100) NOT NULL COMMENT '密码', `email` VARCHAR(100) DEFAULT NULL COMMENT '邮箱', `birthday` DATE DEFAULT NULL COMMENT '生日' ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表'; -- 创建商品表 CREATE TABLE IF NOT EXISTS `product` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '商品id', `name` VARCHAR(255) DEFAULT NULL COMMENT '商品名称', `product_desc` VARCHAR(255) DEFAULT NULL COMMENT '商品描述信息', `price` DECIMAL(10,2) DEFAULT NULL COMMENT '商品价格', `detail` VARCHAR(255) DEFAULT NULL COMMENT '商品详细描述', `num` INT DEFAULT NULL COMMENT '商品库存数量', `img` VARCHAR(255) DEFAULT NULL COMMENT '商品图片路径', `category` VARCHAR(255) DEFAULT NULL COMMENT '商品分类', `status` INT DEFAULT NULL COMMENT '商品状态 0=不可售 1=可售', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表'; -- 插入用户测试数据 INSERT INTO `user` (`name`, `password`, `email`, `birthday`) VALUES ('张三', '123456', 'zhangsan@qq.com', '2000-01-10'), ('李四', '654321', 'lisi@163.com', '1999-05-20'), ('王五', 'abc123', 'wangwu@sina.com', '2001-08-15'); -- 插入商品测试数据 INSERT INTO `product` (`name`, `product_desc`, `price`, `detail`, `num`, `img`, `category`, `status`) VALUES ('Apple iPhone 15 Pro', '苹果旗舰智能手机', 7999.00, '6.7英寸超视网膜XDR显示屏,钛金属设计', 88, 'https://img11.360buyimg.com/xxx.jpg', '手机数码', 1), ('华为 Mate 60 Pro', '华为旗舰商务手机', 6999.00, '卫星通话,昆仑玻璃', 66, 'https://img10.360buyimg.com/xxx.jpg', '手机数码', 1);

运行脚本后,我们的mall数据库就创建好了,两张表也有了基础的测试数据,后续操作就基于这两张表进行。


三、核心工具类:JDBC 连接封装

每次写 JDBC 都要重复加载驱动、获取连接、关闭资源,太麻烦了,我们可以封装一个DButil工具类,统一处理这些操作:

package com.util; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class DButil { // 数据库连接信息,记得改成你自己的账号密码 public static String URL="jdbc:mysql://localhost:3306/mall?serverTimezone=GMT%2B8&useSSL=false"; public static String USERNAME="root"; public static String PASSWORD="你的数据库密码"; public static String DRIVER="com.mysql.jdbc.Driver"; // MySQL 5.x驱动类 // 获取数据库连接 public static Connection getConnection(){ Connection conn=null; try{ Class.forName(DRIVER); // 加载驱动 conn=DriverManager.getConnection(URL,USERNAME,PASSWORD); // 建立连接 }catch (Exception e){ e.printStackTrace(); } return conn; } // 关闭数据库资源(结果集、执行对象、连接) public static void close(ResultSet rs, Statement st,Connection con){ try{ if (rs!=null) rs.close(); if (st!=null) st.close(); if (con!=null) con.close(); }catch (Exception e){ e.printStackTrace(); } } }

封装好之后,后续所有 DAO 层操作,直接调用DButil.getConnection()就能拿到连接,操作完调用close()方法统一关闭资源,代码清爽很多。


四、实体类与 DAO 层实现

1. 实体类(Entity)

用 Lombok 的@Data注解简化实体类,和数据库表字段一一对应:

// User实体类 package com.entity; import lombok.Data; @Data public class User { private int id; private String name; private String password; private String email; private String birthday; public User(){} public User(int id,String name){ this.id=id; this.name=name; } } // Product实体类 package com.entity; import lombok.Data; @Data public class Product { private int id; private String name; private String product_desc; private float price; private String detail; private int num; private String img; private String category; private int status; }

2. 用户 DAO 层(UserDao & UserDao1)

UserDao实现了查询所有用户的功能,UserDao1封装了增、删、改用户的操作:

// UserDao:查询所有用户 package com.dao; import com.entity.User; import com.util.DButil; import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import java.util.ArrayList; import java.util.List; public class UserDao { public List<User> getAll(){ Connection con=null; Statement stmt=null; ResultSet rs=null; List<User> users = new ArrayList<>(); String sql = "select * from User"; try{ con = DButil.getConnection(); stmt = con.createStatement(); rs = stmt.executeQuery(sql); while(rs.next()){ User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setBirthday(rs.getString("birthday")); user.setEmail(rs.getString("email")); user.setPassword(rs.getString("password")); users.add(user); } }catch (Exception e){ e.printStackTrace(); }finally { DButil.close(rs,stmt,con); } return users; } } // UserDao1:用户增删改操作 package com.dao; import com.entity.User; import com.util.DButil; import java.sql.Connection; import java.sql.PreparedStatement; public class UserDao1 { // 新增用户 public int add(User user){ int num = 0; Connection conn = DButil.getConnection(); try{ String sql = "insert into User(name,email,password,birthday) values(?,?,?,?)"; PreparedStatement pst = conn.prepareStatement(sql); pst.setString(1,user.getName()); pst.setString(2,user.getEmail()); pst.setString(3,user.getPassword()); pst.setString(4,user.getBirthday()); num = pst.executeUpdate(); DButil.close(null,pst,conn); }catch (Exception e){ e.printStackTrace(); } return num; } // 修改用户密码 public int updateUser(int id,String password){ int num = 0; Connection conn = DButil.getConnection(); try{ String sql = "update user set password=? where id=?"; PreparedStatement pst = conn.prepareStatement(sql); pst.setString(1,password); pst.setInt(2,id); num = pst.executeUpdate(); DButil.close(null,pst,conn); }catch (Exception e){ e.printStackTrace(); } return num; } // 删除用户 public int deleteUser(int id){ int num = 0; Connection con = DButil.getConnection(); try{ String sql = "delete from user where id = ?"; PreparedStatement pst = con.prepareStatement(sql); pst.setInt(1,id); num = pst.executeUpdate(); DButil.close(null,pst,con); }catch (Exception e){ e.printStackTrace(); } return num; } }

3. 商品 DAO 层(ProductDao & ProductDaoImpl)

先定义 DAO 接口,再写实现类,方便后续扩展:


五、Service 层与 Servlet 层实现

1. 商品 Service 层

Service 层调用 DAO 层方法,处理业务逻辑:

// ProductService接口 package com.service; import com.entity.Product; import java.util.List; public interface ProductService { List<Product> getProductList(); int add(Product product); } // ProductServiceImpl实现类 package com.service; import com.dao.ProductDaoImpl; import com.entity.Product; import java.util.List; public class ProductServiceImpl implements ProductService { ProductDaoImpl pdi = new ProductDaoImpl(); @Override public List<Product> getProductList() { return pdi.getProsuctList(); } @Override public int add(Product product) { return 0; } }

2. ProductServlet:处理请求并转发到 JSP

用 Servlet 接收请求,调用 Service 层获取商品列表,再转发到 JSP 页面展示:

package com.Servlet; import com.service.ProductServiceImpl; import com.entity.Product; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; @WebServlet("/p") public class ProductServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ProductServiceImpl imp = new ProductServiceImpl(); List<Product> products = imp.getProductList(); // 把商品列表存入request域,传递给JSP页面 req.setAttribute("products", products); // 转发到index.jsp页面 req.getRequestDispatcher("index.jsp").forward(req, resp); } }

这里用@WebServlet("/p")注解配置 Servlet 路径,访问/p就会触发这个 Servlet 的doGet方法。


六、JSP 页面渲染数据

最后写一个简单的 JSP 页面,用 JSTL 标签遍历商品列表,展示数据:

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <html> <head> <title>商品列表</title> </head> <body> <h1>商品列表</h1> <c:forEach items="${products}" var="item"> <p>商品ID:${item.id}</p> <p>商品名称:${item.name}</p> <p>商品描述:${item.product_desc}</p> <p>商品价格:${item.price}元</p> <hr> </c:forEach> </body> </html>

isELIgnored="false"是为了让 JSP 支持 EL 表达式,c:forEach标签用来遍历 Servlet 传递过来的products集合。


七、JUnit 单元测试:验证 DAO 层功能

我们写了几个单元测试类,分别测试数据库连接、用户增删改查功能,确保 DAO 层的代码是正确的:

1. 数据库连接测试

import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; public class uint51 { @Test public void test(){ try{ // 1、加载驱动 Class.forName("com.mysql.jdbc.Driver"); // 2、连接信息 String url="jdbc:mysql://localhost:3306/mall?serverTimezone=GMT%2B8&useSSL=false"; String username="你的数据库账号"; String password="你的数据库密码"; // 获取连接 Connection con= DriverManager.getConnection(url,username,password); System.out.println("数据库链接正常"); con.close(); }catch(Exception e){ System.out.println("数据库链接失败"); e.printStackTrace(); } } }

运行测试后,控制台输出数据库链接正常,说明数据库连接没问题。

2. 用户增删改测试

// 新增用户测试 import com.entity.User; import com.dao.UserDao1; import org.junit.Test; public class AddTest { @Test public void test(){ User user = new User(); user.setName("李明"); user.setEmail("lingming@163.com"); user.setPassword("123456"); user.setBirthday("2003-04-20"); UserDao1 userDao1 = new UserDao1(); int num = userDao1.add(user); if (num>0) { System.out.println("插入数据成功了!"); } } } // 删除用户测试 import com.dao.UserDao1; import org.junit.Test; public class deleteTest { @Test public void test(){ UserDao1 userDao1 = new UserDao1(); int num = userDao1.deleteUser(4); if (num > 0){ System.out.println("删除成功!"); } } } // 修改用户密码测试 import com.dao.UserDao1; import org.junit.Test; public class updateTest { @Test public void test(){ UserDao1 userDao1 = new UserDao1(); int num = userDao1.updateUser(1, "newPassword123"); if(num>0){ System.out.println("密码修改成功!"); } } } // 查询所有用户测试 import com.dao.UserDao; import com.entity.User; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class uint52 { @Test public void test(){ UserDao userDao = new UserDao(); List<User> users = new ArrayList<>(); users = userDao.getAll(); for(User u:users){ System.out.println(u); } } }

这些测试都通过后,说明我们的 DAO 层增删改查功能是完全正常的,后续业务开发就可以放心调用了。


八、项目运行效果

把项目部署到 Tomcat 服务器,启动后就能看到 JSP 页面渲染的商品列表了,数据是从 MySQL 数据库里查出来的,实现了最基础的数据库 -> DAO -> Service -> Servlet -> JSP完整流程。

http://www.jsqmd.com/news/712796/

相关文章:

  • 4月28日成都地区华岐产镀锌方矩管(Q235B;直径20-400mm)厂家直供 - 四川盛世钢联营销中心
  • RVC语音转换实战指南:8个核心问题的高效解决方案
  • 如何精准解决机械键盘连击问题:Keyboard Chatter Blocker场景化实战指南
  • 2026亲测:8款降AI神器,AI率真能降80%?论文救星含红黑榜避坑 - 降AI实验室
  • 确保REST API安全:Nonce的正确使用
  • .NET生态集成:在C#应用中调用万象熔炉·丹青幻境服务
  • 如何快速在iOS 14-16.6.1设备上安装TrollStore:TrollInstallerX完整指南
  • 基于MCP协议构建Java WHOIS查询服务器,无缝集成AI助手工作流
  • 小白必看!WuliArt Qwen-Image Turbo使用全攻略:写提示词技巧+常见问题解决
  • Silicon Labs低成本蓝牙SoC BG22L/BG24L解析与选型指南
  • AI 技术日报 - 2026-04-28
  • 2026 AI搜索优化必备,免费GEO监测工具实测
  • 机器学习预备知识
  • 2026市场比较好的化工pvdf管生产商推荐榜 - 品牌排行榜
  • 【大模型-SLAM】LingBot-Map:Geometric Context Transformer for Streaming 3D Reconstruction
  • Phi-3-mini-4k-instruct-gguf Chainlit生产化:Nginx负载均衡+HTTPS证书配置
  • 4月28日成都地区华岐产螺旋焊管(Q235B;内径DN200-3500mm)厂家直供 - 四川盛世钢联营销中心
  • Qwen-Image-Layered实战体验:5分钟部署,像编辑PSD一样编辑AI图片
  • AI Agent开发入门:基于Nanbeige 4.1-3B构建自主任务执行智能体
  • 【2026年版|收藏级】RAG系统延迟优化实战:从链路拆解到面试通关,小白也能看懂
  • Azure DevOps 中的权限问题:Docker镜像上传的误区与解决之道
  • NVIDIA Profile Inspector完整指南:解锁隐藏显卡设置,彻底解决游戏性能问题
  • 从JSP到Vue单文件:用FileViewProvider理解IDEA如何‘读懂’混合语言文件
  • Vulkan 入门教程五:命令缓冲、同步机制与渲染循环
  • 广东省CPPM官方报名中心授权机构及联系方式(官方正规报名通道) - 中供国培
  • 电磁 + 散热 + 电路全仿真,看懂新版 ANSYS 2025 详细下载安装教程附安装包
  • postgresql 拼接字段
  • 算力市场转型深度解析:从建设部署到行业赋能,核心趋势与实践路径
  • 基于SimAM无参数注意力机制的YOLOv10改进:提升目标检测性能的新范式
  • AI Agent 记忆机制详解:程序员进阶大模型开发必备(收藏版)