从零到一:用Java+Servlet+JSP手把手搭建一个鲜花商城(附完整源码和数据库设计)
·
从零到一:用Java+Servlet+JSP手把手搭建一个鲜花商城(附完整源码和数据库设计)
如果你正在寻找一个完整的Java Web项目实战教程,或是为毕业设计发愁,这篇指南将带你从零开始构建一个功能完善的鲜花商城系统。不同于纸上谈兵的理论分析,我们将聚焦于 可落地的代码实现 ,涵盖环境搭建、数据库设计、前后台功能开发等全流程。即使你是Servlet/JSP的初学者,也能跟着步骤完成项目。
1. 环境准备与项目初始化
1.1 开发工具清单
- JDK 1.8+ :Java开发的基础环境
- Eclipse/IntelliJ IDEA :推荐使用后者,对Web开发支持更友好
- Tomcat 9.x :Servlet容器
- MySQL 5.7+ :数据库服务
- Navicat/MySQL Workbench :数据库可视化工具
1.2 创建Web项目
在IDE中新建Dynamic Web Project,确保勾选生成 web.xml 。项目结构应包含:
/flower-shop
├── src
├── WebContent
│ ├── META-INF
│ ├── WEB-INF
│ │ ├── lib (存放依赖jar包)
│ │ └── web.xml
│ ├── css
│ ├── js
│ └── images
添加必要依赖到 lib 目录:
mysql-connector-java-8.0.x.jarjstl-1.2.jarservlet-api.jar
2. 数据库设计与实现
2.1 数据表结构
采用MySQL设计5张核心表:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`email` varchar(100) NOT NULL,
`phone` varchar(20) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`register_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
UNIQUE KEY `username_UNIQUE` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
其他表包括:
category(鲜花分类)product(鲜花商品)cart(购物车)orders(订单)
提示:字段设计需考虑扩展性,如价格使用DECIMAL而非FLOAT避免精度问题
2.2 数据库连接池配置
在 WEB-INF/web.xml 中添加:
<resource-ref>
<description>MySQL Datasource</description>
<res-ref-name>jdbc/flowerDB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
创建 DBUtil.java 处理连接:
public class DBUtil {
private static DataSource ds;
static {
try {
Context ctx = new InitialContext();
ds = (DataSource) ctx.lookup("java:comp/env/jdbc/flowerDB");
} catch (NamingException e) {
e.printStackTrace();
}
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
}
3. 前台功能开发实战
3.1 用户认证模块
实现注册/登录的Servlet示例:
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = SHA256Util.encrypt(request.getParameter("password"));
try (Connection conn = DBUtil.getConnection()) {
String sql = "INSERT INTO user(username, password, email) VALUES(?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
pstmt.setString(3, request.getParameter("email"));
int result = pstmt.executeUpdate();
if(result > 0) {
request.getSession().setAttribute("user", username);
response.sendRedirect("index.jsp");
}
} catch (SQLException e) {
request.setAttribute("error", "用户名已存在");
request.getRequestDispatcher("register.jsp").forward(request, response);
}
}
}
3.2 商品展示系统
商品列表JSP页面关键代码:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<table class="product-table">
<c:forEach items="${products}" var="p">
<tr>
<td><img src="uploads/${p.image}" width="120"></td>
<td>${p.name}</td>
<td>¥${p.price}</td>
<td>
<a href="product_detail?id=${p.id}">查看详情</a>
<button onclick="addToCart(${p.id})">加入购物车</button>
</td>
</tr>
</c:forEach>
</table>
对应的Servlet:
@WebServlet("/product_list")
public class ProductListServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String categoryId = request.getParameter("cid");
List<Product> products = new ArrayList<>();
try (Connection conn = DBUtil.getConnection()) {
String sql = "SELECT * FROM product WHERE status=1";
if(categoryId != null) {
sql += " AND category_id=" + categoryId;
}
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
Product p = new Product();
p.setId(rs.getInt("id"));
// 其他字段赋值...
products.add(p);
}
} catch (SQLException e) {
e.printStackTrace();
}
request.setAttribute("products", products);
request.getRequestDispatcher("product_list.jsp").forward(request, response);
}
}
4. 后台管理系统开发
4.1 管理员登录验证
使用Filter实现权限控制:
@WebFilter("/admin/*")
public class AdminFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
if(session.getAttribute("admin") == null) {
((HttpServletResponse)response).sendRedirect("../admin_login.jsp");
return;
}
chain.doFilter(request, response);
}
}
4.2 商品管理功能
文件上传处理Servlet:
@WebServlet("/admin/product_upload")
@MultipartConfig(
fileSizeThreshold = 1024 * 1024 * 1, // 1MB
maxFileSize = 1024 * 1024 * 10, // 10MB
maxRequestSize = 1024 * 1024 * 100 // 100MB
)
public class ProductUploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Part filePart = request.getPart("product_image");
String fileName = System.currentTimeMillis() + "_" +
filePart.getSubmittedFileName();
String uploadPath = getServletContext().getRealPath("") + "uploads";
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) uploadDir.mkdir();
filePart.write(uploadPath + File.separator + fileName);
// 保存到数据库
try (Connection conn = DBUtil.getConnection()) {
String sql = "INSERT INTO product(name, price, image) VALUES(?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, request.getParameter("name"));
pstmt.setBigDecimal(2, new BigDecimal(request.getParameter("price")));
pstmt.setString(3, fileName);
pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
response.sendRedirect("product_list.jsp");
}
}
5. 项目部署与优化
5.1 Tomcat部署要点
- 导出WAR包:
右键项目 → Export → WAR file - 部署到Tomcat的
webapps目录 - 配置
conf/server.xml的Context:
<Context
docBase="/path/to/flower-shop"
path="/flowershop"
reloadable="true"
source="org.eclipse.jst.jee.server:flower-shop"/>
5.2 性能优化技巧
- 数据库连接池 :配置Tomcat的
context.xml - 静态资源缓存 :在
web.xml中添加:
<filter>
<filter-name>ExpiresFilter</filter-name>
<filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class>
<init-param>
<param-name>ExpiresByType image</param-name>
<param-value>access plus 1 month</param-value>
</init-param>
</filter>
- JSP预编译 :使用
jspc工具提前编译
6. 常见问题解决方案
6.1 中文乱码处理
全局编码过滤器:
@WebFilter("/*")
public class EncodingFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
chain.doFilter(request, response);
}
}
6.2 分页查询实现
分页工具类核心方法:
public class Pagination<T> {
private int pageSize = 10;
private int currentPage;
private int totalCount;
private List<T> items;
// 计算总页数
public int getTotalPages() {
return (int) Math.ceil((double)totalCount / pageSize);
}
// SQL分页语句生成
public static String getPageSql(String baseSql, int page, int size) {
return baseSql + " LIMIT " + (page-1)*size + "," + size;
}
}
7. 项目扩展方向
- 支付接口集成 :接入支付宝沙箱环境
- 搜索优化 :实现Elasticsearch商品搜索
- 缓存机制 :引入Redis缓存热门商品
- 安全加固 :增加CSRF防护和XSS过滤
完整项目源码已托管至GitHub,包含详细的README和SQL脚本。在实际开发中遇到最多的问题是JSP页面元素定位,建议使用Chrome开发者工具逐步调试CSS样式。
更多推荐
所有评论(0)