实现购物车,有很多的方法,我这次用的session,使用oracle数据库来存取数据
1、数据库设计(就一个表:商品表 items),并插入几条测试数据
2、利用MVC的思想来设计整个项目的结构,如下所示
3、首先设计po包,主要有:Items.java Cart.java
package cn.hpe.po;
/**
* 商品实体类
* @author CCQ
* @date 2016年9月17日
*/
public class Items {
private String pid; //商品编号
private String pname;//商品名称
private String city;//产地
private double price;//价格
private int pnum;//库存
private String pic;//商品图片
//保留此不带参数的构造方法
public Items(){
}
//带参数的构造方法
public Items(String pid, String pname, String city, double price, int pnum,
String pic) {
this.pid = pid;
this.pname = pname;
this.city = city;
this.price = price;
this.pnum = pnum;
this.pic = pic;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getPnum() {
return pnum;
}
public void setPnum(int pnum) {
this.pnum = pnum;
}
public String getPic() {
return pic;
}
public void setPic(String pic) {
this.pic = pic;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((pid == null) ? 0 : pid.hashCode());
result = prime * result + ((pname == null) ? 0 : pname.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Items))
return false;
Items other = (Items) obj;
if (pid == null) {
if (other.pid != null)
return false;
} else if (!pid.equals(other.pid))
return false;
if (pname == null) {
if (other.pname != null)
return false;
} else if (!pname.equals(other.pname))
return false;
return true;
}
}
package cn.hpe.po;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* 购物车实体(添加、删除和计算价格)
*
* @author CCQ
* @date 2016年9月17日
*/
public class Cart {
private HashMap<Items, Integer> goods; // 购买的商品集合
private double totalPrice; // 购物车的总金额
// 构造方法
public Cart() {
goods = new HashMap<Items, Integer>();
totalPrice = 0;
}
public HashMap<Items, Integer> getGoods() {
return goods;
}
public void setGoods(HashMap<Items, Integer> goods) {
this.goods = goods;
}
public double getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(double totalPrice) {
this.totalPrice = totalPrice;
}
// 添加商品进购物车的方法
public boolean addGoodsInCart(Items item, int number) {
if (goods.containsKey(item)) {
goods.put(item, goods.get(item) + number);
} else {
goods.put(item, number);
}
calTotalPrice(); // 重新计算购物车的总金额
return true;
}
// 统计购物车的总金额
public double calTotalPrice() {
double sum = 0;
Set<Items> keys = goods.keySet(); // 获得键的集合
Iterator<Items> it = keys.iterator(); // 获得迭代器的对象
while (it.hasNext()) {
Items i = it.next();
sum += i.getPrice() * goods.get(i);
}
this.setTotalPrice(sum); // 设置购物车的总金额
return this.getTotalPrice();
}
// 删除商品的方法
public boolean removeGoodsFromCart(Items item) {
goods.remove(item);
calTotalPrice();// 重新计算购物车总金额
return true;
}
//测试购物车的添加和计算总的金额
public static void main(String[] args) {
// 先创建两个商品对象
Items i1 = new Items("1", "沃特篮球鞋", "温州", 200, 500, "001.jpg");
Items i2 = new Items("2", "李宁运动鞋", "广州", 300, 500, "002.jpg");
Items i3 = new Items("1", "沃特篮球鞋", "温州", 200, 500, "001.jpg");
Cart c = new Cart();
c.addGoodsInCart(i1, 1);
c.addGoodsInCart(i2, 2);
// 再次购买沃特篮球鞋,购买3双
c.addGoodsInCart(i3, 3);
// 变量购物商品的集合
Set<Map.Entry<Items, Integer>> items = c.getGoods().entrySet();
for (Map.Entry<Items, Integer> obj : items) {
System.out.println(obj);
}
Set<Items> keys = c.getGoods().keySet(); // 获得键的集合
Iterator<Items> it = keys.iterator(); // 获得迭代器的对象
while (it.hasNext()) {
Items i = it.next();
System.out.println(i.getPname()+"=="+c.getGoods().get(i));
}
System.out.println("购物车的总金额:" + c.getTotalPrice());
}
}
其中购物车类中需要注意的是:在写购物车的无参构造方法时,先初始化goods和total=0,这是很重要的,
然后有添加到购物车的方法(addGoodsInCart(Items item, int number))
把物品从购物车中移除方法(removeGoodsFromCart(Items item))
计算购物车总的金额方法(calTotalPrice())
其中在向购物车中添加商品时,用到了containsKey()方法,其本质是比较hashCode是否相等,所以在Items中必须重写equals和hashCode方法
4、编写数据访问层dao:主要是对商品的处理IItemsDao()接口和它的实现类ItemsDaoImpl()
package cn.hpe.dao.interfaces;
import java.util.List;
import cn.hpe.po.Items;
public interface IItemsDao {
/**
* 查询所有的商品
* @return
* @throws Exception
*/
public List<Items> getAllItems() throws Exception;
/**
* 根据商品id查询商品
* @param pid
* @return
* @throws Exception
*/
public Items getItemById(String pid) throws Exception;
}
package cn.hpe.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import cn.hpe.dao.config.BaseDao;
import cn.hpe.dao.interfaces.IItemsDao;
import cn.hpe.po.Items;
/**
* 商品操作实现类
* @author CCQ
* @date 2016年9月17日
*/
public class ItemsDaoImpl implements IItemsDao {
@Override
public List<Items> getAllItems() throws Exception {
// TODO Auto-generated method stub
List<Items> items = null;
BaseDao baseDao = new BaseDao();
try{
Connection conn = baseDao.getConnection();
String sql = "select * from items";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
items = new ArrayList<Items>();
while(rs.next()){
Items item = new Items();
item.setPid(rs.getString("pid"));
item.setPname(rs.getString("pname"));
item.setCity(rs.getString("city"));
item.setPnum(rs.getInt("pnum"));
item.setPrice(rs.getDouble("price"));
item.setPic(rs.getString("pic"));
items.add(item);
}
baseDao.closeConn(rs, ps, conn);
}catch(Exception e){
throw new Exception(e);
}
return items;
}
@Override
public Items getItemById(String pid) throws Exception {
// TODO Auto-generated method stub
Items item = null;
BaseDao baseDao = new BaseDao();
try{
Connection conn = baseDao.getConnection();
String sql = "select * from items where pid = ?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setObject(1, pid);
ResultSet rs = ps.executeQuery();
if(rs.next()){
item = new Items();
item.setPid(rs.getString("pid"));
item.setPname(rs.getString("pname"));
item.setCity(rs.getString("city"));
item.setPnum(rs.getInt("pnum"));
item.setPrice(rs.getDouble("price"));
item.setPic(rs.getString("pic"));
}
baseDao.closeConn(rs, ps, conn);
}catch(Exception e){
throw new Exception(e);
}
return item;
}
}
还有就是baseDao,其中使用数据源实现和数据库的链接,需要在tomcat中配置一下数据源
package cn.hpe.dao.config;
import java.sql.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
/**
* 连接oracle数据库类,使用连接池的方法
*
* @author CCQ
*
*/
public class BaseDao {
public Connection getConnection() throws Exception {
System.out.println("开始使用连接池...");
Connection conn = null;
try {
Context context = new InitialContext();
DataSource ds = (DataSource) context
.lookup("java:comp/env/jdbc/gm");
conn = ds.getConnection();
} catch (Exception e) {
throw new Exception(e);
}
return conn;
}
/**
* 关闭数据库连接
*/
public void closeConn(ResultSet rs, PreparedStatement ps, Connection conn)
throws Exception {
try {
if (rs != null) {
rs.close();
}
if (ps != null) {
ps.close();
}
if (conn != null) {
conn.close();
}
} catch (Exception ex) {
throw new Exception(ex);
}
}
}
在tomcat中的配置:
<Resource name="jdbc/gm"
auth="Container" type="javax.sql.DataSource" maxActive="100"
maxIdle="30" maxWait="10000" username="gm" password="123456"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@localhost:1521:orcl"
/>
5、在书写services包,注意异常向外抛,最后在servlet中在进行处理
package cn.hpe.services.interfaces;
import java.util.List;
import cn.hpe.po.Items;
public interface IItemsService {
/**
* 查询所有的商品
* @return
* @throws Exception
*/
public List<Items> getAllItems() throws Exception;
/**
* 根据商品id查询商品
* @param pid
* @return
* @throws Exception
*/
public Items getItemById(String pid) throws Exception;
}
package cn.hpe.services.impl;
import java.util.List;
import cn.hpe.dao.impl.ItemsDaoImpl;
import cn.hpe.dao.interfaces.IItemsDao;
import cn.hpe.po.Items;
import cn.hpe.services.interfaces.IItemsService;
public class ItemsServiceImpl implements IItemsService{
@Override
public List<Items> getAllItems() throws Exception {
// TODO Auto-generated method stub
IItemsDao itemsDao = new ItemsDaoImpl();
List<Items> items = null;
try{
items = itemsDao.getAllItems();
}catch(Exception e){
throw new Exception(e);
}
return items;
}
@Override
public Items getItemById(String pid) throws Exception {
// TODO Auto-generated method stub
IItemsDao itemsDao = new ItemsDaoImpl();
Items item = null;
try{
item = itemsDao.getItemById(pid);
}catch(Exception e){
throw new Exception(e);
}
return item;
}
}
6、数据控制层:servlet的书写,主要有商品控制:ItemsServlet和CartServlet
package cn.hpe.action;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hpe.po.Items;
import cn.hpe.services.impl.ItemsServiceImpl;
import cn.hpe.services.interfaces.IItemsService;
public class ItemsServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
IItemsService itemsService = new ItemsServiceImpl();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String op = request.getParameter("option");
if ("list".equals(op)) {
itemList(request, response);
}
if ("item".equals(op)) {
itemDetails(request, response);
}
}
// 显示所有的商品
public void itemList(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
List<Items> items = new ArrayList<Items>();
items = itemsService.getAllItems();
request.setAttribute("items", items);
request.getRequestDispatcher("index.jsp")
.forward(request, response);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 显示商品的详细信息
public void itemDetails(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String pid = request.getParameter("pid");
Items item = new Items();
item = itemsService.getItemById(pid);
request.setAttribute("item", item);
request.getRequestDispatcher("details.jsp")
.forward(request, response);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package cn.hpe.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hpe.po.Cart;
import cn.hpe.po.Items;
import cn.hpe.services.impl.ItemsServiceImpl;
import cn.hpe.services.interfaces.IItemsService;
/**
* 购物车的Servlet
*
* @author CCQ
* @date 2016年9月17日
*/
public class CartServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
IItemsService itemsService = new ItemsServiceImpl();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
String op = request.getParameter("option");
if ("add".equals(op)) {
addToCart(request, response);
String pid = request.getParameter("pid");
response.sendRedirect("ItemsServlet?pid="+pid+"&option=item");
} else if ("show".equals(op)) {
cartList(request, response);
} else if ("delete".equals(op)) {
deleteFromCart(request, response);
request.getRequestDispatcher("CartServlet?option=show").forward(request, response);
}
}
// 添加商品进购物车
public boolean addToCart(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String pid = request.getParameter("pid");
int num = Integer.parseInt(request.getParameter("num"));
Items item = itemsService.getItemById(pid);
// 是否是第一次给购物车添加商品时,需要给session中创建一个新的购物车对象
if (request.getSession().getAttribute("cart") == null) {
Cart cart = new Cart();
request.getSession().setAttribute("cart", cart);
}
Cart cart = (Cart) request.getSession().getAttribute("cart");
if (cart.addGoodsInCart(item, num)) {
cart = (Cart) request.getSession().getAttribute("cart");
return true;
} else {
return false;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
// 从购物车删除商品
public boolean deleteFromCart(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String pid = request.getParameter("pid");
Cart cart = (Cart) request.getSession().getAttribute("cart");
Items item = itemsService.getItemById(pid);
if (cart.removeGoodsFromCart(item)) {
return true;
} else {
return false;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return false;
}
// 显示购物车
public void cartList(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
Cart cartMap = (Cart) request.getSession().getAttribute("cart");
request.setAttribute("cartMap", cartMap);
request.getRequestDispatcher("cartList.jsp").forward(request, response);
}
}
7、最后的就是前台JSP页面的设计,我的设计就是简单地排版,哈哈
(1)商品显示主页面 index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>商品展示页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
div {
float: left;
text-align: center;
}
</style>
</head>
<body>
<h1>商品展示</h1>
<hr>
<table>
<tr>
<td><c:forEach items="${items }" var="item">
<div>
<dl>
<dd>
<a href="ItemsServlet?option=item&pid=${item.pid}"> <img
src="images/${item.pic }" width="120" height="90" border="1" /></a>
</dd>
<dd>${item.pname }</dd>
<dd>产地:${item.city }</dd>
<dd>价格:¥${item.price }</dd>
</dl>
</div>
</c:forEach></td>
</tr>
</table>
</body>
</html>
(2)商品详细信息显示页面 details.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>商品详细信息页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
table {
margin: 0 auto;
}
span {
display: inline-block;
border: 1px solid #cccccc;
width: 15px;
height: 20px;
cursor: pointer;
text-align: center;
}
#sub {
margin-right: -10px;
border-right-width: 0px;
}
#add {
margin-left: -10px;
border-left-width: 0px;
}
#number {
text-align: center;
}
</style>
</head>
<body>
<h1>商品详情</h1>
<a href="ItemsServlet?option=list">首页</a> >>
<a href="ItemsServlet?option=list">商品列表</a>
<hr>
<table>
<tr>
<td rowspan="4"><img src="images/${item.pic }" width="200"
height="160" /></td>
</tr>
<tr>
<td>${item.pname }</td>
</tr>
<tr>
<td>产地:${item.city }</td>
</tr>
<tr>
<td>价格:¥${item.price }</td>
</tr>
<tr>
<td>购买数量:<span id="sub" οnclick="sub()">-</span> <input
type="text" id="number" name="number" value="1" size="2" /> <span
id="add" οnclick="add()">+</span>
</td>
</tr>
<tr>
<td>
<div id="cart">
<img src="images/in_cart.png" οnclick="addCart()">
<a href="CartServlet?option=show"> <img
src="images/view_cart.jpg" />
</a>
</div>
</td>
</tr>
</table>
</body>
<script type="text/javascript">
function sub() {
var number = parseInt(document.getElementById("number").value);
if (number > 1) {
document.getElementById("number").value = --number;
}
}
function add() {
var number = parseInt(document.getElementById("number").value);
if (number < 100) {
document.getElementById("number").value = ++number;
}
}
function addCart() {
var num = document.getElementById("number").value;
document.location.href = "CartServlet?pid=${item.pid}&option=add&num="+num;
alert("添加成功!");
}
</script>
</html>
(3)显示购物车 cartList.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>购物车</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
<style type="text/css">
table {
margin: 0 auto;
text-align: center;
margin-top: 50px;
}
td {
height: 80px;
}
span {
display: inline-block;
float: right;
margin-top: 25px;
margin-right: 50px;
}
</style>
</head>
<body>
<h1>我的购物车</h1>
<a href="ItemsServlet?option=list">首页</a> >>
<a href="ItemsServlet?option=list">商品列表</a>
<hr />
<table border="1px" cellpadding="0" cellspacing="0">
<tr>
<th>商品名称</th>
<th>商品单价</th>
<th>商品价格</th>
<th>购买数量</th>
<th>操作</th>
</tr>
<c:forEach items="${cartMap.goods }" var="c">
<tr>
<td width="300px"><img width="100px" src="images/${c.key.pic} " /><span>${c.key.pname }</span></td>
<td width="200px">${c.key.price }元</td>
<td width="200px">${c.key.price*c.value }元</td>
<td width="200px">${c.value }件</td>
<td width="200px"><a
href="CartServlet?option=delete&pid=${c.key.pid }"
οnclick="delcfm();"> 删除 </a></td>
</tr>
</c:forEach>
<tr>
<td colspan="5">总计:${cartMap.totalPrice}元</td>
</tr>
</table>
</body>
<script language="javascript">
function delcfm() {
if (!confirm("确认要删除?")) {
window.event.returnValue = false;
}
}
</script>
</html>
8、项目运行结果展示