功能简述
本例采用jsp+servlet+mysql+jdbc+c3p0+ajax简单实现一个购物车的功能。
- 项目结构
service那层可以忽略,就不实现登录的功能了,还得加过滤器,主要就实现购物车就行了
JQ + jar包
链接:https://pan.baidu.com/s/1KN8EvSlraH_tHaynzW3znw
提取码:86je
复制这段内容后打开百度网盘手机App,操作更方便哦
项目源码:
链接:https://pan.baidu.com/s/1HjRL67r8JJg5KM2jhKthLA
提取码:4i2r
复制这段内容后打开百度网盘手机App,操作更方便哦
具体实现
在开发购物车之前,首先要把几个关键类之间的关系理清楚
首先各个类的意义:
- Product 产品
- User 用户
- Order 订单
- OrderItem 订单项
前3者都好理解,订单项需要解释一下。
比如阁下在某宝下了一次订单,这个订单包括了
黑色的丝袜 一条
娃娃 两个
抹布 三个
蜡烛 四个
一条记录就是一个订单项,对应一种商品,以及购买数量。
第一步建立product并且进行展示
在本地数据库中创建数据库cart
create database cart;
-
建立商品表product
CREATE TABLEproduct
(
id
int(11) DEFAULT NULL,
name
varchar(50) DEFAULT NULL,
price
float DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8; -
插入数据
insert into product values(1,‘黑色的丝袜’,500);
insert into product values(2,‘娃娃’,2500);
insert into product values(3,‘抹布’,180);
insert into product values(4,‘蜡烛’,0.20); -
product实体类
-
jdbc工具类
package com.chenchangjie.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JDBCUtil {
private static ComboPooledDataSource dataSource;
static {
dataSource = new ComboPooledDataSource("testc3p0");
}
public static Connection getConnection() throws SQLException {
Connection connection = null;
connection = dataSource.getConnection();
return connection;
}
public static void Close(ResultSet resultSet, PreparedStatement statement,Connection connection) throws SQLException {
if(resultSet != null)
resultSet.close();
if(statement != null)
statement.close();
if(connection != null)
connection.close();
}
}
- c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<named-config name="testc3p0">
<!--指定连接池的初始属性-->
<property name="jdbcUrl">jdbc:mysql://localhost:3306/cart?characterEncoding=utf-8&serverTimezone=UTC</property>
<property name="user">root</property>
<property name="password">你的密码</property>
<property name="driverClass">com.mysql.cj.jdbc.Driver</property>
<!--初始化连接池中的连接数量-->
<property name="initialPoolSize">20</property>
<!--请求过多时能连接的最大数量-->
<property name="maxPoolSize">40</property>
<!--一次可以递增的连接数量-->
<!--当连接池中剩余两个就开始递增-->
<property name="acquireIncrement">10</property>
<!--当连接池中到达最低剩余数量时,开始递增-->
<property name="minPoolSize">2</property>
</named-config>
</c3p0-config>
package com.chenchangjie.eneity;
public class Product {
private int id;
private String name;
private float price;
public Product(int id, String name, float price) {
this.id = id;
this.name = name;
this.price = price;
}
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;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
- 从数据库中查询商品的接口以及实现类(还有通过id获取商品后面会用到)
package com.chenchangjie.Repository;
import com.chenchangjie.eneity.Product;
import java.util.List;
public interface ProductRepository {
List<Product> returnProduct();
Product getProductById(int id);
}
实现类ProductRepositoryImpl.java
package com.chenchangjie.Repository.impl;
import com.chenchangjie.Repository.ProductRepository;
import com.chenchangjie.eneity.Product;
import com.chenchangjie.utils.JDBCUtil;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ProductRepositoryImpl implements ProductRepository {
@Override
public List<Product> returnProduct() {
List<Product> list = new ArrayList<>();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = JDBCUtil.getConnection();
String sql = "select * from product order by id";
statement = connection.prepareStatement(sql);
resultSet = statement.executeQuery();
while(resultSet.next()){
list.add(new Product(resultSet.getInt("id"),resultSet.getString("name"),resultSet.getFloat("price")));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
try {
JDBCUtil.Close(resultSet,statement,connection);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return list;
}
@Override
public Product getProductById(int id) {
Product product = null;
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = JDBCUtil.getConnection();
String sql = "select * from product where id = ?";
statement = connection.prepareStatement(sql);
statement.setInt(1,id);
resultSet = statement.executeQuery();
while (resultSet.next()){
product = new Product(resultSet.getInt(1),resultSet.getString(2),resultSet.getFloat(3));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return product;
}
}
- productServlet.java通过接收前端的数据和请求然后响应回去,响应的数据来源就是上面的
ProductRepositoryImpl.java
package com.chenchangjie.servlet;
import com.chenchangjie.Repository.ProductRepository;
import com.chenchangjie.Repository.impl.ProductRepositoryImpl;
import com.chenchangjie.eneity.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("/productList")
public class ProductServlet extends HttpServlet {
private ProductRepository productRepository = new ProductRepositoryImpl();
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
List<Product> list = productRepository.returnProduct();
req.setAttribute("list",list);
req.getRequestDispatcher("index.jsp").forward(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
}
}
index.jsp
```html
<%--
Created by IntelliJ IDEA.
User: 陈老C
Date: 2020-12-9
Time: 15:21
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>Title</title>
<script type="text/javascript" src="/js/jquery-1.7.2.js"></script>
<script type="text/javascript">
$(function () {
// console.log("login");
$("button.AddCartBtn").click(function () {
// console.log("click");
let num = parseInt($("input.num").val());
let pid = parseInt($(this).attr("pid"));
// console.log(num + " " + pid);
$.ajax({
url:'/addOrderItem',
type:'post',
dataType:'text',
data:'type=add&pid=' + pid + '&num=' + num,
success:function (data) {
alert("添加购物车成功")
}
});
})
});
</script>
</head>
<body>
<c:if test="${!empty user}">
<div align="center">
当前用户: ${user.name}
</div>
</c:if>
<table align='center' border='1' cellspacing='0'>
<tr>
<td>id</td>
<td>名称</td>
<td>价格</td>
<td>购买</td>
</tr>
<c:forEach items="${list}" var="product" varStatus="st">
<tr>
<td>${product.id}</td>
<td>${product.name}</td>
<td>${product.price}</td>
<td>数量<input class="num" type="text" value="1" name="num">
<%-- <input id="addCart" type="submit" value="购买">--%>
<!--多个部件不用id选择器,用类选择器-->
<button class="AddCartBtn" pid="${product.id}">加入购物车</button>
</td>
</tr>
</c:forEach>
</table>
<a href="listOrderItem.jsp">购物车</a>
<%--<form action="/productList" method="get">
<input type="submit" value="购物车"/>--%>
</body>
</html>
然后访问localhost:8080/productList
就能看见商品
点击加入购物车按钮就会进入/addOrderItem
进入相应的逻辑处理,这里是通过ajax异步请求到/addOrderItem
里面;
- OrderItemAddServlet.java
package com.chenchangjie.servlet;
import com.chenchangjie.Repository.ProductRepository;
import com.chenchangjie.Repository.impl.ProductRepositoryImpl;
import com.chenchangjie.eneity.OrderItem;
import com.chenchangjie.eneity.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.ArrayList;
import java.util.List;
@WebServlet("/addOrderItem")
public class OrderItemAddServlet extends HttpServlet {
private ProductRepository productRepository = new ProductRepositoryImpl();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int num = Integer.parseInt(req.getParameter("num"));
int pid = Integer.parseInt(req.getParameter("pid"));
String type = req.getParameter("type");
Product product = productRepository.getProductById(pid);
OrderItem orderItem = new OrderItem(product,num);
List<OrderItem> list = (List<OrderItem>) req.getSession().getAttribute("ois");
if(list == null){
list = new ArrayList<>();
req.getSession().setAttribute("ois",list);
}
//检查是否有重复的数量
boolean flag = false;
for(OrderItem o : list){
if(o.getProduct().getId() == product.getId()){
o.setNum(o.getNum() + num);
flag = true;
break;
}
}
if(!flag)
list.add(orderItem);
resp.sendRedirect("index.jsp");
}
}
- listOrderItem.jsp展示购物车里面的内容
<%--
Created by IntelliJ IDEA.
User: 陈老C
Date: 2020-12-9
Time: 17:14
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*" isELIgnored="false"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<h1 align="center" >购物车</h1>
<table align='center' border='1' cellspacing='0'>
<tr>
<td>商品名称</td>
<td>单价</td>
<td>数量</td>
<td>小计</td>
</tr>
<c:forEach items="${ois}" var="oi" varStatus="st">
<tr>
<td>${oi.product.name}</td>
<td>${oi.product.price}</td>
<td>${oi.num}</td>
<td>${oi.product.price*oi.num}</td>
<td>
<a href="/deleteOrderItem?pName=${oi.product.name}" type="delete">删除</a>
</td>
</tr>
</c:forEach>
</table>
<a href="/productList">回到购物页面</a>