在当今数字化零售浪潮中,传统中小型百货商店面临着营业时间与物理空间的双重限制。为应对这一挑战,一套基于J2EE经典技术栈的B2C电子商务解决方案应运而生。该系统采用JSP与Servlet作为核心技术框架,结合MySQL数据库,构建了一个功能完备的在线百货商城平台。
系统架构与技术栈设计
该系统严格遵循MVC设计模式,实现了表示层、控制层与业务逻辑层的清晰分离。Servlet作为核心控制器,负责拦截所有HTTP请求,进行初步参数验证后,调用相应的业务逻辑处理单元,最终根据处理结果选择转发至对应的JSP视图页面。
// 用户登录Servlet示例
public class UserLoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String loginName = request.getParameter("loginName");
String password = request.getParameter("password");
UserService userService = new UserServiceImpl();
User user = userService.login(loginName, password);
if(user != null) {
HttpSession session = request.getSession();
session.setAttribute("loginUser", user);
response.sendRedirect("index.jsp");
} else {
request.setAttribute("errorMsg", "用户名或密码错误");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
表示层采用JSP技术,通过嵌入JSTL标签库和EL表达式实现数据的动态渲染,有效避免了在页面中直接编写Java代码,保证了代码的可读性与可维护性。CSS和JavaScript负责前端样式和交互逻辑的实现,为用户提供流畅的购物体验。
数据库设计深度解析
商品表设计分析
easybuy_product表作为系统的核心数据表,其设计体现了电商系统的典型特征:
CREATE TABLE `easybuy_product` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键',
`name` varchar(255) NOT NULL COMMENT '名称',
`description` varchar(1024) DEFAULT NULL COMMENT '描述',
`price` float NOT NULL COMMENT '价格',
`stock` int(10) NOT NULL COMMENT '库存',
`categoryLevel1Id` int(10) DEFAULT NULL COMMENT '分类1',
`categoryLevel2Id` int(10) DEFAULT NULL COMMENT '分类2',
`categoryLevel3Id` int(10) DEFAULT NULL COMMENT '分类3',
`fileName` varchar(255) DEFAULT NULL COMMENT '文件名称',
`isDelete` int(1) DEFAULT 0 COMMENT '是否删除(1:删除 0:未删除)',
PRIMARY KEY (`id`),
UNIQUE KEY `PK__EASYBUY___94F6E55132E0915F` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=771 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='商品表'
该表采用三级分类体系,支持灵活的商品分类管理。isDelete字段实现逻辑删除功能,避免物理删除导致的数据丢失风险。价格字段使用float类型,适用于电商场景下的价格计算,但在实际生产环境中建议使用Decimal类型以确保精度。
订单详情表设计
easybuy_order_detail表的设计体现了订单处理的核心理念:
CREATE TABLE `easybuy_order_detail` (
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键',
`orderId` int(10) NOT NULL COMMENT '订单主键',
`productId` int(10) NOT NULL COMMENT '商品主键',
`quantity` int(10) NOT NULL COMMENT '数量',
`cost` float NOT NULL COMMENT '消费',
PRIMARY KEY (`id`),
UNIQUE KEY `PK__EASYBUY___66E1BD8E2F10007B` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='订单详情表'
该表通过orderId与订单主表关联,productId与商品表关联,实现了订单与商品的多对多关系。cost字段存储下单时的商品价格,确保订单历史价格的准确性,不受后续商品价格变动的影响。
用户表安全设计
easybuy_user表在用户管理方面采用了合理的安全设计:
CREATE TABLE `easybuy_user` (
`id` int(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`loginName` varchar(255) NOT NULL COMMENT '登录名',
`userName` varchar(255) NOT NULL COMMENT '用户名',
`password` varchar(255) NOT NULL COMMENT '密码',
`sex` int(2) NOT NULL DEFAULT 1 COMMENT '性别(1:男 0:女)',
`identityCode` varchar(60) DEFAULT NULL COMMENT '身份证号',
`email` varchar(80) DEFAULT NULL COMMENT '邮箱',
`mobile` varchar(11) DEFAULT NULL COMMENT '手机',
`type` int(2) DEFAULT 0 COMMENT '类型(1:后台 0:前台)',
PRIMARY KEY (`id`),
UNIQUE KEY `PK__EASYBUY___C96109CC3A81B327` (`loginName`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci COMMENT='用户表'
loginName字段设置唯一约束,防止重复注册。type字段区分前后台用户权限,实现基于角色的访问控制。在实际应用中,密码字段应存储加密后的哈希值而非明文。
核心业务功能实现
购物车模块设计与实现
购物车作为电商系统的核心组件,其实现采用了面向对象的设计思想:
public class Cart {
private double totalMoney;
private List<CartItem> cartItems = new ArrayList<CartItem>();
/**
* 添加到购物车中
*/
public void addCart(Product product, String num) {
CartItem cartItem = getExistsItem(product.getId());
if(cartItem == null) {
cartItem = new CartItem();
cartItem.setGoNum(Integer.parseInt(num));
cartItem.setProduct(product);
cartItem.setCost(1 * product.getPrice());
cartItems.add(cartItem);
} else {
cartItem.setGoNum(cartItem.getGoNum() + Integer.parseInt(num));
cartItem.setCost(product.getPrice() * cartItem.getGoNum());
}
}
/**
* 判断商品是否存在于购物车中
*/
public CartItem getExistsItem(int productId) {
for (CartItem cartItem : cartItems) {
if(cartItem.getProduct().getId() == productId) {
return cartItem;
}
}
return null;
}
}

购物车模块采用Session存储方案,确保用户在浏览过程中的购物车状态持久化。addCart方法实现了商品的重复添加逻辑,当同一商品多次加入时自动累加数量并重新计算金额。
商品管理功能实现
后台商品管理模块提供了完整的CRUD操作:
public class ProductServiceImpl implements ProductService {
public List<Product> findAllProduct() {
String sql = "select * from easybuy_product where isDelete=0";
return BaseDao.executeQuery(Product.class, sql);
}
public Product findProductById(int id) {
String sql = "select * from easybuy_product where id=? and isDelete=0";
List<Product> list = BaseDao.executeQuery(Product.class, sql, id);
return list.size() > 0 ? list.get(0) : null;
}
public int updateProduct(Product product) {
String sql = "update easybuy_product set name=?,description=?,price=?,stock=?,categoryLevel1Id=?,categoryLevel2Id=?,categoryLevel3Id=?,fileName=? where id=?";
return BaseDao.executeUpdate(sql, product.getName(), product.getDescription(),
product.getPrice(), product.getStock(), product.getCategoryLevel1Id(),
product.getCategoryLevel2Id(), product.getCategoryLevel3Id(),
product.getFileName(), product.getId());
}
}

商品管理采用软删除策略,通过isDelete字段控制商品的显示状态。分类字段支持三级分类体系,满足百货商城复杂的商品分类需求。
订单处理流程实现
订单生成涉及多个数据表的协同操作:
public class OrderServiceImpl implements OrderService {
public boolean addOrder(Order order, List<CartItem> cartItems) {
Connection conn = null;
try {
conn = BaseDao.getConnection();
conn.setAutoCommit(false);
// 插入订单主表
String orderSql = "insert into easybuy_order(userId,loginName,userAddress,createTime,cost,serialNumber) values(?,?,?,?,?,?)";
int orderId = BaseDao.executeInsert(conn, orderSql, order.getUserId(), order.getLoginName(),
order.getUserAddress(), order.getCreateTime(), order.getCost(), order.getSerialNumber());
// 插入订单明细
for(CartItem item : cartItems) {
String detailSql = "insert into easybuy_order_detail(orderId,productId,quantity,cost) values(?,?,?,?)";
BaseDao.executeUpdate(conn, detailSql, orderId, item.getProduct().getId(),
item.getGoNum(), item.getCost());
// 更新商品库存
String stockSql = "update easybuy_product set stock=stock-? where id=?";
BaseDao.executeUpdate(conn, stockSql, item.getGoNum(), item.getProduct().getId());
}
conn.commit();
return true;
} catch (Exception e) {
if(conn != null) {
try { conn.rollback(); } catch (SQLException ex) {}
}
return false;
}
}
}

订单处理采用数据库事务确保数据一致性,在订单创建过程中同时更新库存信息,防止超卖现象的发生。
用户权限管理实现
系统通过type字段实现前后台用户权限分离:
public class UserFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession session = req.getSession();
User user = (User) session.getAttribute("loginUser");
String requestURI = req.getRequestURI();
// 后台管理路径需要管理员权限
if(requestURI.contains("/admin/")) {
if(user == null || user.getType() != 1) {
resp.sendRedirect(req.getContextPath() + "/login.jsp");
return;
}
}
chain.doFilter(request, response);
}
}

权限控制通过Filter实现,对访问后台管理功能的请求进行拦截验证,确保只有管理员身份的用户可以访问相应功能。
实体模型设计
系统采用面向对象的实体模型设计,每个数据库表对应一个实体类:
public class Product {
private int id;
private String name;
private String description;
private float price;
private int stock;
private int categoryLevel1Id;
private int categoryLevel2Id;
private int categoryLevel3Id;
private String fileName;
private int isDelete;
// Getter和Setter方法
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
// 其他Getter和Setter方法...
}
实体类通过封装数据库字段,提供了面向对象的操作接口,业务逻辑层通过操作实体对象来完成数据持久化操作。
数据访问层设计
系统采用统一的数据访问层实现数据库操作:
public class BaseDao {
public static Connection getConnection() {
Connection conn = null;
try {
Context context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:comp/env/jdbc/easybuy");
conn = dataSource.getConnection();
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
public static int executeUpdate(String sql, Object... params) {
Connection conn = null;
PreparedStatement pstmt = null;
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
for(int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
return pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
return 0;
} finally {
closeAll(conn, pstmt, null);
}
}
public static <T> List<T> executeQuery(Class<T> clazz, String sql, Object... params) {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
List<T> list = new ArrayList<T>();
try {
conn = getConnection();
pstmt = conn.prepareStatement(sql);
for(int i = 0; i < params.length; i++) {
pstmt.setObject(i + 1, params[i]);
}
rs = pstmt.executeQuery();
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
while(rs.next()) {
T obj = clazz.newInstance();
for(int i = 1; i <= columnCount; i++) {
String columnName = metaData.getColumnLabel(i);
Object value = rs.getObject(i);
Field field = clazz.getDeclaredField(columnName);
field.setAccessible(true);
field.set(obj, value);
}
list.add(obj);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
closeAll(conn, pstmt, rs);
}
return list;
}
}
数据访问层采用反射机制实现通用查询方法,减少了重复代码的编写,提高了开发效率。
系统优化与功能扩展建议
性能优化方向
- 数据库连接池优化:采用Druid等高性能连接池替代基础实现,配置合理的连接参数
- 查询缓存机制:对热点商品数据实施Redis缓存,减少数据库访问压力
- 静态资源分离:将商品图片等静态资源部署至CDN或对象存储服务
功能扩展建议
- 支付集成:集成支付宝、微信支付等第三方支付平台,完善交易闭环
- 搜索引擎:引入Elasticsearch实现商品全文检索和智能推荐
- 移动端适配:开发响应式布局或独立的移动端应用,满足移动购物需求
安全增强措施
- 密码加密:使用BCrypt等强哈希算法替代MD5加密
- SQL注入防护:全面使用PreparedStatement,添加输入验证过滤器
- 会话安全:实现会话超时机制和并发登录控制
该系统作为J2EE经典技术栈的实践案例,展现了MVC架构在Web应用开发中的优势,为中小型零售企业提供了可靠的电商解决方案,同时也为Java Web开发者提供了宝贵的学习参考。通过持续优化和功能扩展,该系统有望成为更加完善的电子商务平台。