Web-第二十二天 Web商城实战二【悟空教程】
今日内容介绍
今日内容学习目标
-- 2.1 创建分类表
CREATE TABLE `category` (
`cid` varchar(32) NOT NULL,
`cname` varchar(20) DEFAULT NULL, #分类名称
PRIMARY KEY (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 2.2 初始化分类默认数据
INSERT INTO `category` VALUES ('1','手机数码'),('172934bd636d485c98fd2d3d9cccd409','运动户外'),('2','电脑办公'),('3','家具家居'),('4','鞋靴箱包'),('5','图书音像'),('59f56ba6ccb84cb591c66298766b83b5','aaaa'),('6','母婴孕婴'),('afdba41a139b4320a74904485bdb7719','汽车用品');
public class Category {
private String cid;
private String cname;
/**
* 分类模块dao层的接口
*
*/
public interface CategoryDao {
}
/**
* 分类模块dao层的实现类
*
*/
public class CategoryDaoImpl implements CategoryDao {
}
/**
* 分类模块service层的接口
*
*/
public interface CategoryService {
}
package cn.com.javahelp.store.service.impl;
/**
* 分类模块service层的接口
*/
public class CategoryServiceImpl implements CategoryService {
}
作者:余华
当当 广告
购买
public class IndexServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
public String execute(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 查询所有的分类
CategoryService categoryService = new CategoryServiceImpl();
List<Category> allCategory = categoryService.findAll();
// 将查询结果存放request作用域
request.setAttribute("allCategory", allCategory);
return "/jsp/index.jsp";
}
}
//接口
public interface CategoryService {
/**
* 查询所有
* @return
*/
List<Category> findAll();
}
//实现类
public class CategoryServiceImpl implements CategoryService {
private CategoryDao categoryDao = new CategoryDaoImpl();
@Override
public List<Category> findAll() {
return categoryDao.findAll();
}
}
//接口
/**
* 分类模块dao层的接口
*
*/
public interface CategoryDao {
/**
* 查询所有
* @return
*/
List<Category> findAll() throws SQLException;
}
//实现类
/**
* 分类模块dao层的实现类
*
*/
public class CategoryDaoImpl implements CategoryDao {
@Override
public List<Category> findAll() throws SQLException{
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource() );
String sql = "select * from category";
return queryRunner.query(sql, new BeanListHandler<Category>(Category.class));
}
}
<%--激活 <li> --%>
<c:forEach items="${allCategory}" var="category">
<li value="${category.cid}"><a href="#">${category.cname}</a></li>
</c:forEach>
当访问首页时可以显示分类导航条,但访问其他模块时无法访问显示分类。通过比较程序我们发现,显示首页前我们查询了所有分类,显示登录等其他模块时我们没有查询分类。为了所有模块都可以显示分类,我们需要发送ajax单独查询分类。
<script type="text/javascript">
<!--
$(function(){
var url = "${pageContext.request.contextPath}/CategoryServlet";
$.post(url,{"method":"findAll"} ,function(data){
$.each(data,function(i,n){
$("#menu").append("<li value=''><a href='#'>"+n.cname+"</a></li>");
});
});
});
//-->
</script>
public class CategoryServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
//ajax查询所有
public String findAll(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 1.1查询所有的分类
CategoryService categoryService = new CategoryServiceImpl();
List<Category> allCategory = categoryService.findAll();
// 1.2 将查询结果转换成json
String jsonStr = JSONArray.fromObject(allCategory).toString();
// 1.3 将结果响应给浏览器
response.setContentType("application/json;charset=UTF-8");
response.getWriter().print(jsonStr);
return null;
}
}
<servlet>
<servlet-name>CategoryServlet</servlet-name>
<servlet-class>cn.com.javahelp.store.web.servlet.CategoryServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CategoryServlet</servlet-name>
<url-pattern>/CategoryServlet</url-pattern>
</servlet-mapping>
当我们在不同模块之间切换时,发现菜单栏显示的分类数据都是一样的。浏览器每发送一次请求,服务器端都会查询一次数据库,从而对数据库服务器造成不必要的访问。实际开发中,我们采用缓存技术来解决此类问题。
/**
* 查询分类通过缓存服务器
*/
public String findAllByAjax() throws Exception {
Jedis j =null;
String value=null;
try {
//从redis获取分类信息
//1.获取连接
j = JedisUtils.getJedis();
//2.获取数据 判断数据是否为空
value = j.get("category_list");
//2.1 若不为空,直接返回数据
if(value!=null){
System.out.println("缓存中有数据库");
return value;
}
//2.2 若为空,从mysql数据库中获取 并放入redis中
List<Category> clist = findAll();
//将clist转成json返回且放入redis中即可
value=JsonUtil.list2json(clist);
//将value放入redis中
j.set("category_list", value);
return value;
} finally {
//释放jedis
JedisUtils.close(j);
}
}
public class JedisUtils {
//创建连接池
private static JedisPoolConfig config;
private static JedisPool pool;
static{
config=new JedisPoolConfig();
config.setMaxTotal(30);
config.setMaxIdle(2);
pool=new JedisPool(config, "192.168.17.132", 6379);
}
//获取连接的方法
public static Jedis getJedis(){
return pool.getResource();
}
//释放资源
public static void close(Jedis j) {
if(j != null){
j.close();
}
}
}
-- 3.1 创建商品表
CREATE TABLE `product` (
`pid` varchar(32) NOT NULL,
`pname` varchar(50) DEFAULT NULL, #商品名称
`market_price` double DEFAULT NULL, #商场价
`shop_price` double DEFAULT NULL, #商城价
`pimage` varchar(200) DEFAULT NULL, #商品图片路径
`pdate` date DEFAULT NULL, #上架时间
`is_hot` int(11) DEFAULT NULL, #是否热卖
`pdesc` varchar(255) DEFAULT NULL, #商品描述
`pflag` int(11) DEFAULT 0, #商品标记:0=未下架(默认值),1=已经下架
`cid` varchar(32) DEFAULT NULL, #分类id
PRIMARY KEY (`pid`),
KEY `product_fk_0001` (`cid`),
CONSTRAINT `product_fk_0001` FOREIGN KEY (`cid`) REFERENCES `category` (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 3.2 初始化商品默认数据
INSERT INTO `product` VALUES ('1','小米 4c 标准版',1399,1299,'products/1/c_0001.jpg','2015-11-02',1,'小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待',0,'1'),('10','华为 Ascend Mate7',2699,2599,'products/1/c_0010.jpg','2015-11-02',1,'华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!',0,'1')
参考:
public class Product {
private String pid;
private String pname;
private Double market_price;
private Double shop_price;
private String pimage;
private Date pdate;
private Integer is_hot; // 0 不是热门 1:热门
private String pdesc;
private Integer pflag; // 0 未下架 1:已经下架
// 分类,以面向对象的方式描述商品与分类之间的关系
// * 多个商品属于一个分类
private Category category;
/**
* 商品dao接口
*/
public interface ProductDao {
}
/**
* 商品dao实现类
*/
public class ProductDaoImpl implements ProductDao {
}
/**
* 商品service接口
*/
public interface ProductService {
}
/**
* 商品service实现类
*/
public class ProductServiceImpl implements ProductService {
}
public class ProductServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
}
<servlet>
<servlet-name>ProductServlet</servlet-name>
<servlet-class>cn.com.javahelp.store.web.servlet.ProductServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ProductServlet</servlet-name>
<url-pattern>/ProductServlet</url-pattern>
</servlet-mapping>
public class IndexServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
public String execute(HttpServletRequest request, HttpServletResponse response)
throws Exception {
ProductService productService = new ProductServiceImpl();
// 1.1 查询热门商品:
List<Product> hotList = productService.findByHot();
// 1.2 查询最新商品:
List<Product> newList = productService.findByNew();
// 2 将查询结果存放
request.setAttribute("hotList",hotList);
request.setAttribute("newList",newList);
return "/jsp/index.jsp";
}
}
// 接口
public interface ProductService {
/**
* 热门商品
* @return
*/
List<Product> findByHot() throws SQLException;
/**
* 最新商品
* @return
*/
List<Product> findByNew() throws SQLException;
}
//实现类
public class ProductServiceImpl implements ProductService {
private ProductDao productdao = new ProductDaoImpl();
@Override
public List<Product> findByHot() throws SQLException{
return productdao.findByHot();
}
@Override
public List<Product> findByNew() throws SQLException{
return productdao.findByNew();
}
}
// 接口
public interface ProductDao {
/**
* 热门商品
* @return
* @throws SQLException
*/
List<Product> findByHot() throws SQLException;
/**
* 最新商品
* @return
* @throws SQLException
*/
List<Product> findByNew() throws SQLException;
}
//实现类
public class ProductDaoImpl implements ProductDao {
@Override
public List<Product> findByHot() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from product where is_hot=? and pflag = ? order by pdate desc limit ?";
List<Product> list = queryRunner.query(sql, new BeanListHandler<Product>(Product.class), 1,0,9);
return list;
}
@Override
public List<Product> findByNew() throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from product where pflag = ? order by pdate desc limit ?";
List<Product> list = queryRunner.query(sql, new BeanListHandler<Product>(Product.class),0,9);
return list;
}
}
<%--热门商品列表 --%>
<c:forEach var="p" items="${ hotList }">
<div style="text-align:center;height:200px;padding:10px 0px;">
<a href="#">
<img src="${ pageContext.request.contextPath }/${ p.pimage}" ...>
</a>
<p><a href="#" style='color:#666'>${ p.pname }</a></p>
<p><font color="#E4393C" style="font-size:16px">¥${ p.shop_price }</font></p>
</div>
</c:forEach>
<%--最新商品列表 --%>
<c:forEach var="p" items="${ newList }">
<div style="text-align:center;height:200px;padding:10px 0px;">
<a href="#">
<img src="${ pageContext.request.contextPath }/${ p.pimage }" ...>
</a>
<p><a href="#" style='color:#666'>${ p.pname }</a></p>
<p><font color="#E4393C" style="font-size:16px">¥${ p.shop_price }</font></p>
</div>
</c:forEach>
public class ProductServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
//通过id查询详情
public String findById(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 1 接收参数:
String pid = request.getParameter("pid");
// 2 通知service进行查询
ProductService productService = new ProductServiceImpl();
Product product = productService.findById(pid);
// 3.1 将查询结果存放作用域
request.setAttribute("product",product);
// 3.2 页面跳转
return "/jsp/product_info.jsp";
}
}
//接口
/**
* 通过id查询详情
* @param pid
* @return
*/
Product findById(String pid) throws SQLException
//实现类
@Override
public Product findById(String pid) throws SQLException {
return productDao.findById(pid);
}
//接口
/**
* 通过id查询详情
* @param pid
* @return
*/
Product findById(String pid) throws SQLException;
//实现类
@Override
public Product findById(String pid) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from product where pid = ?";
Product product = queryRunner.query(sql, new BeanHandler<Product>(Product.class), pid);
return product;
}
//支持分页,如果没有传递默认值1
$("#menu").append("<li value=''><a href='${pageContext.request.contextPath}/ProductServlet?method=findByCid&cid="+n.cid+"'>"+n.cname+"</a></li>");
//通过分类id查询所有商品
public String findByCid(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 1 接收参数
// 1.1 分类id
String cid = request.getParameter("cid");
// 1.2 当前页
int pageNumber = 1;
try {
//没有传递参数,或参数错误,使用默认值1
pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
} catch (Exception e) {
}
// 1.3 每页显示个数
int pageSize = 12; //固定值,可以通过请求参数获得
// 2 调用业务层:
ProductService productService = new ProductServiceImpl();
PageBean<Product> pageBean = productService.findByCid(cid,pageNumber,pageSize);
// 3 将数据存放request作用域,并请求转发到指定的jsp
request.setAttribute("pageBean", pageBean);
return "/jsp/product_list.jsp";
}
public class PageBean<T> {
private int pageNumber; //当前页(浏览器传递)
private int pageSize; //每页显示个数(固定值,也可以是浏览器传递)
private int totalRecord; //总记录数(数据库查询)
private int totalPage; //总分页数
private int startIndex; //开始索引
private List<T> data; //分页数据(数据库查询)
public PageBean(int pageNumber, int pageSize, int totalRecord) {
this.pageNumber = pageNumber;
this.pageSize = pageSize;
this.totalRecord = totalRecord;
// 成员变量和局部变量重名,此处统一使用成员变量,及都需要添加“this.”
//#1 总分页数
this.totalPage = (this.totalRecord + this.pageNumber - 1) / this.pageSize;
//#2 开始索引
this.startIndex = (this.pageNumber-1) * pageSize;
}
//接口
/**
* 分页查询所有商品
* @param cid
* @param pageNumber
* @param pageSize
* @return
*/
PageBean<Product> findByCid(String cid, int pageNumber, int pageSize) throws SQLException;
//实现类
public PageBean<Product> findByCid(String cid, int pageNumber, int pageSize) throws SQLException {
//1 获得总记录数
int totalRecord = productDao.findTotalRecordByCid(cid);
//2 封装数据
PageBean<Product> pageBean = new PageBean<>(pageNumber, pageSize, totalRecord);
//3 分页数据
List<Product> data = productDao.findAllByCid(cid, pageBean.getStartIndex() , pageBean.getPageSize());
pageBean.setData(data);
return pageBean;
}
//接口
/**
* 查询总记录(含分页)
* @param cid
* @return
* @throws SQLException
*/
int findTotalRecordByCid(String cid) throws SQLException;
/**
* 查询指定分类的所有书籍(含分页)
* @param cid
* @param startIndex
* @param pageSize
* @return
* @throws SQLException
*/
List<Product> findAllByCid(String cid, int startIndex, int pageSize) throws SQLException;
//实现类
@Override
public int findTotalRecordByCid(String cid) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select count(*) from product where cid = ?";
Long count = (Long) queryRunner.query(sql, new ScalarHandler(), cid);
return count.intValue();
}
@Override
public List<Product> findAllByCid(String cid, int startIndex, int pageSize) throws SQLException {
QueryRunner queryRunner = new QueryRunner(JDBCUtils.getDataSource());
String sql = "select * from product where cid = ? and pflag = ? order by pdate desc limit ?,?";
List<Product> list = queryRunner.query(sql, new BeanListHandler<Product>(Product.class), cid,0,startIndex,pageSize);
return list;
}
<c:forEach items="${pageBean.data}" var="product">
<div style="height:240px;" >
<a href="${pageContext.request.contextPath}/ProductServlet?method=findById&pid=${product.pid}">
<img src="${pageContext.request.contextPath}/${product.pimage}" ….>
</a>
<p><a href="${pageContext.request.contextPath}/ProductServlet?method=findById&pid=${product.pid}">
<c:if test="${fn:length(product.pname) lt 27 }"> ${product.pname}</c:if>
<c:if test="${fn:length(product.pname) ge 27 }"> ${fn:substring(product.pname,0,27)} ...</c:if>
</a></p>
<p><font color="#FF0000">商城价:¥${product.shop_price}</font></p>
</div>
</c:forEach>
1)拷贝easyui资源
2)导入easyui css和js
<%--easyui --%>
<link rel="stylesheet" type="text/css"href="../js/easyui/themes/icon.css" />
<link rel="stylesheet" type="text/css"href="../js/easyui/themes/bootstrap/easyui.css" />
<script type="text/javascript"src="../js/easyui/jquery.easyui.min.js" ></script>
3)使用 $.pagination 显示分页条,并设置回调函数
<div style="width:600px;margin:0 auto;margin-top:50px;">
<div>
<div id="paginationId"style="font-size:14px;margin:0;display:block;"></div>
</div>
<script type="text/javascript">
$(function(){
$("#paginationId").pagination({
total:'${pageBean.totalRecord}', //总记录数
pageSize:'${pageBean.pageSize}', //每页显示个数
pageNumber:'${param.pageNumber}', //当前页
layout:['first','prev','sep','links','sep','next','last','sep','manual'],//布局
beforePageText:'当前第',
//显示跳转文本框,enter键触发
afterPageText:'页,共{pages}页',
displayMsg:'当前显示{from}到{to}条,共{total}条记录', //显示记录信息
onSelectPage:function(pageNumber, pageSize){ //页面改变是触发
location.href = "${pageContext.request.contextPath}/ProductServlet?method=findByCid&&cid=${param.cid}&pageNumber=" + pageNumber;
}
});
});
</script>
/**浏览历史记录start*/
// #1 获得cookie
Cookie cookie = CookieUtils.findCookie(request.getCookies(), "history");
// #2 拼凑商品id ,将结果以cookie方式响应给浏览器
if(cookie == null){
// 第一次浏览商品.
Cookie c = new Cookie("history",pid);
c.setPath("/");
c.setMaxAge(7 * 24 * 60 * 60);
response.addCookie(c);
}else{
// 不是第一次浏览商品.
String value = cookie.getValue();// 1-2-3
String[] ids = value.split("-");
LinkedList<String> list = new LinkedList<String>(Arrays.asList(ids));
if(list.contains(pid)){
// 已经浏览过
list.remove(pid);
list.addFirst(pid);
}else{
// 没有浏览过该商品
if(list.size() >=6){
list.removeLast();
list.addFirst(pid);
}else{
list.addFirst(pid);
}
}
StringBuffer sb = new StringBuffer();
for (String id : list) {
sb.append(id+"-");
}
String history = sb.substring(0, sb.length()-1);
Cookie c = new Cookie("history",history);
c.setPath("/");
c.setMaxAge(7 * 24 * 60 * 60);
response.addCookie(c);
}
/**浏览历史记录end*/
<%
Cookie cookie = CookieUtils.findCookie(request.getCookies(), "history");
if(cookie != null){
String value = cookie.getValue();
String[] ids = value.split("-"); //2-1-3
ProductService productService = new ProductServiceImpl();
for(String pid : ids){
Product product = productService.findById(pid);
pageContext.setAttribute("p", product);
%>
<ul style="list-style: none;">
<li style="width: 150px;height: 216;float: left;margin: 0 8px 0 0;padding: 0 18px 15px;text-align: center;"><img src="${pageContext.request.contextPath}/${p.pimage}" width="130px" height="130px" /></li>
</ul>
<%
}
}
%>
昨天我们已经完成商品信息的查询,接着将允许用户通过商城进行商品的购买。通过浏览器访问商城,就相当于去超市购买商品,我们需要使用“购物车”对准备购买商品的增删操作。
/**
* 购物项的实体:用于封装某一类商品的购买情况
*/
public class CartItem {
private Product product; // 购买的商品的信息
private int count; // 购买的数量
private double subtotal; // 购买商品的小计,计算获得:商品的单价 * 购买数量
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public double getSubtotal() {
this.subtotal = count * product.getShop_price();
return this.subtotal;
}
/*//因为是计算获得,所以不需要setter方法
* public void setSubtotal(double subtotal) {
this.subtotal = subtotal;
}*/
}
/**
* 购物车的对象
*/
public class Cart {
/* #1 定义一个购物项的集合的属性,用于维护所有的购物项,集合采用Map<String,Product>
* 1) map.key : 商品的id
* 2) map.value : 商品信息
* * 采用Map集合,方便通过商品ID(key)获得商品信息(value)
*/
private Map<String,CartItem> map = new LinkedHashMap<String,CartItem>();
// #2 定义购物车中的总计,添加、删除等操作不进行计算,直接获得时一并计算
private double total;
// #3 提供购物项集合属性,方便页面获取数据
/*public Map<String, CartItem> getMap() {
return map;
}*/
// 相当于属性名为:cartItems
public Collection<CartItem> getCartItems(){
return map.values();
}
// #4 计算获得总计
public double getTotal() {
total = 0;
for (Map.Entry<String, CartItem> entry : map.entrySet()) {
CartItem cartItem = entry.getValue();
total += cartItem.getSubtotal();
}
return total;
}
// # 5.1 方法:添加商品到购物车
public void addCart(Product product , int count){
if(product == null){
return; //
}
// 通过商品id获得购物项
CartItem cartItem = map.get(product.getPid());
// 第一次购买
if(cartItem == null){
cartItem = new CartItem();
cartItem.setProduct(product);
cartItem.setCount(count);
// 将购物项添加到购物车
map.put(product.getPid(), cartItem);
} else {
cartItem.setCount(cartItem.getCount() + count);
}
// 计算总计
// total += cartItem.getSubtotal(); //存在同一个商品累加
// total += count * product.getShop_price();
}
// 5.2 方法:从购物车中移除购物项
public void removeCart(String id){
// 从map中移除选中的元素.
// CartItem cartItem = map.get(id);
CartItem cartItem = map.remove(id);
// 将总计 - 移除购物项的小计
// total -= cartItem.getSubtotal();
}
// 5.3 方法:清空购物车
public void clearCart(){ //
// 将map集合清空.
map.clear();
// 将总结设置为0.
// total = 0;
}
}
<script type="text/javascript">
function subForm(){
document.getElementById("form1").submit();// 提交表单
}
</script>
<form id="form1" action="${pageContext.request.contextPath}/CartServlet?method=addToCart" method="post">
<%--隐藏字段,设置商品id --%>
<input type="hidden" name="pid" value="${product.pid}" />
购买数量:<input name="count" value="1" > </div>
<%--加入到购物车 --%>
<a href="javascript:void(0)" onclick="subForm()">加入购物车</a>
</form>
//实现类
public class CartServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
}
// 配置文件
<servlet>
<servlet-name>CartServlet</servlet-name>
<servlet-class>cn.com.javahelp.store.web.servlet.CartServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CartServlet</servlet-name>
<url-pattern>/CartServlet</url-pattern>
</servlet-mapping>
// 添加商品到购物车
public String addToCart(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//1 获得请求参数
// * 商品id
String pid = request.getParameter("pid");
// * 购买数量商品id
Integer count = Integer.parseInt(request.getParameter("count"));
// 2.1 通过id查询详情
ProductService productService = new ProductServiceImpl();
Product product = productService.findById(pid);
// 2.2 获得购物车
Cart cart = getCart(request.getSession());
// 2.3 将商品添加到购物车
cart.addCart(product, count);
// 3 重定向到购物车
response.sendRedirect(request.getContextPath() + "/jsp/cart.jsp");
return null;
}
/**
* 获得购物车
* @param session
* @return
*/
private Cart getCart(HttpSession session) {
Cart cart = (Cart) session.getAttribute("cart");
if(cart == null){
cart = new Cart();
session.setAttribute("cart", cart);
}
return cart;
}
<c:forEach items="${cart.cartItems}" var="cartItem">
<tr>
<td width="60" width="40%">
<input type="hidden" name="id" value="22">
<img src="${pageContext.request.contextPath}/${cartItem.product.pimage}" width="70" height="60">
</td>
<td width="30%">
<a target="_blank">${cartItem.product.pname}</a>
</td>
<td width="20%">
¥${cartItem.product.shop_price}
</td>
<td width="10%">
${cartItem.count}
</td>
<td width="15%">
<span>¥${cartItem.subtotal}</span>
</td>
<td>
<a href="javascript:;">删除</a>
</td>
</tr>
</c:forEach>
商品金额: <strong style="color:#ff6600;">¥${cart.total}元</strong>
<a href="${pageContext.request.contextPath}/CartServlet?method=clearCart" id="clear">清空购物车</a>
// 清空购物车
public String clearCart(HttpServletRequest request, HttpServletResponse response)
throws Exception {
// 1 获得购物车
Cart cart = getCart(request.getSession());
// 2 清空购物车
cart.clearCart();
// 3 重定向到购物车
response.sendRedirect(request.getContextPath() + "/jsp/cart.jsp");
return null;
}
<c:if test="${empty cart || empty cart.cartItems }">
您还没有购买任何商品
</c:if>
<c:if test="${not (empty cart || empty cart.cartItems) }">
//购物车代码
</c:if>
<a href="${pageContext.request.contextPath}/CartServlet?method=removeCart&pid=${cartItem.product.pid}">删除</a>
// 从购物车移除商品
public String removeCart(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//1 获得请求参数,商品id
String pid = request.getParameter("pid");
// 2.1 获得购物车
Cart cart = getCart(request.getSession());
// 2.2 将商品从购物车移除
cart.removeCart(pid);
// 3 重定向到购物车
response.sendRedirect(request.getContextPath() + "/jsp/cart.jsp");
return null;
}
用户已经可以成功将商品添加到购物车,接着我们将进行订单操作,将准备购买的商品变成已购买的商品。
-- 4 创建订单表
CREATE TABLE `orders` (
`oid` varchar(32) NOT NULL,
`ordertime` datetime DEFAULT NULL, #下单时间
`total` double DEFAULT NULL, #总价
`state` int(11) DEFAULT NULL, #订单状态:1=未付款;2=已付款,未发货;3=已发货,没收货;4=收货,订单结束
`address` varchar(30) DEFAULT NULL, #收获地址
`name` varchar(20) DEFAULT NULL, #收获人
`telephone` varchar(20) DEFAULT NULL, #收货人电话
`uid` varchar(32) DEFAULT NULL,
PRIMARY KEY (`oid`),
KEY `order_fk_0001` (`uid`),
CONSTRAINT `order_fk_0001` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 5 创建订单项表
CREATE TABLE `orderitem` (
`itemid` varchar(32) NOT NULL,
`count` int(11) DEFAULT NULL, #购买数量
`subtotal` double DEFAULT NULL, #小计
`pid` varchar(32) DEFAULT NULL, #购买商品的id
`oid` varchar(32) DEFAULT NULL, #订单项所在订单id
PRIMARY KEY (`itemid`),
KEY `order_item_fk_0001` (`pid`),
KEY `order_item_fk_0002` (`oid`),
CONSTRAINT `order_item_fk_0001` FOREIGN KEY (`pid`) REFERENCES `product` (`pid`),
CONSTRAINT `order_item_fk_0002` FOREIGN KEY (`oid`) REFERENCES `orders` (`oid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/**
* 订单的实体
* 实体中定义的属性 尽量使用包装类的类型.
* * 基本数据类型默认值0;包装类默认值是null.
*/
public class Order {
private String oid;
private Date ordertime;
private Double total;
private Integer state; //1=未付款;2=已付款,未发货;3=已发货,没收货;4=收货,订单结束
private String address;
private String name;
private String telephone;
private User user;// 订单所属的用户
// 订单项的集合
private List<OrderItem> list = new ArrayList<OrderItem>();
/**
* 订单详情的实体
*/
public class OrderItem {
private String itemid;
private Integer count;
private Double subtotal;
private Product product; // 订单项中的商品的信息
private Order order; // 订单项属于哪个订单
/**
* 订单dao接口
*/
public interface OrderDao {
}
/**
* 订单dao实现类
*/
public class OrderDaoImpl implements OrderDao {
}
/**
* 订单service接口
*/
public interface OrderService {
}
/**
* 订单service实现类
*/
public class OrderServiceImpl implements OrderService {
}
public class OrderServlet extends BaseServlet {
private static final long serialVersionUID = 1L;
}
<servlet>
<servlet-name>OrderServlet</servlet-name>
<servlet-class>cn.com.javahelp.store.web.servlet.OrderServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>OrderServlet</servlet-name>
<url-pattern>/OrderServlet</url-pattern>
</servlet-mapping>
<a href="${pageContext.request.contextPath}/OrderServlet?method=saveOrder">提交订单
// 添加订单
public String saveOrder(HttpServletRequest request, HttpServletResponse response)
throws Exception {
//1 获得数据
// 1.1 获得购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
// 1.2 获得登录用户
User loginUser = (User) request.getSession().getAttribute("loginUser");
if(loginUser == null){
request.setAttribute("msg", "请先登录,在继续购买");
return "/jsp/login.jsp";
}
// 2 封装数据:
Order order = new Order();
// 2.1 服务器自动生成
order.setOid(UUIDUtils.getUUID());
order.setState(1);// 未付款
order.setOrdertime(new Date());
// 2.2 设置总金额
order.setTotal(cart.getTotal());
// 2.3 设置所属的用户
order.setUser(loginUser);
// 2.4 设置订单项的集合
// * 遍历购物车中的购物项:
for(CartItem cartItem:cart.getCartItems()){
// 将购物项中的数据 转换到 订单详情对象
OrderItem orderItem = new OrderItem();
orderItem.setItemid(UUIDUtils.getUUID());
orderItem.setCount(cartItem.getCount());
orderItem.setSubtotal(cartItem.getSubtotal());
orderItem.setProduct(cartItem.getProduct());
orderItem.setOrder(order);
order.getList().add(orderItem);
}
// 2.5 调用业务层:
OrderService orderService = new OrderServiceImpl();
orderService.save(order);
// 2.6 清空购物车:
cart.clearCart();
// 3 页面跳转
request.setAttribute("order", order);
return "/jsp/order_info.jsp";
}
//接口
public interface OrderService {
//保存订单
void save(Order order) throws SQLException;
}
//实现类
public class OrderServiceImpl implements OrderService {
@Override
// 业务层保存订单的方法:
public void save(Order order) {
// 获得Connection
Connection conn = JDBCUtils.getConnection();
try{
// 调用DAO
OrderDao orderDao = (OrderDao) BeanFactory.getBean("orderDao");
orderDao.save(conn,order);
// 调用DAO
for(OrderItem orderItem :order.getList()){
orderDao.save(conn,orderItem);
}
// 提交事务
DbUtils.commitAndCloseQuietly(conn);
}catch(Exception e){
DbUtils.rollbackAndCloseQuietly(conn);
e.printStackTrace();
}
}
}
//接口
public interface OrderDao {
/**
* 保存订单
* @param conn
* @param order
*/
void save(Connection conn, Order order) throws SQLException;
/**
* 保存订单详情
* @param conn
* @param orderItem
*/
void save(Connection conn, OrderItem orderItem) throws SQLException;
}
//实现类
public class OrderDaoImpl implements OrderDao {
@Override
public void save(Connection conn, Order order) throws SQLException{
QueryRunner queryRunner = new QueryRunner();
String sql = "insert into orders values (?,?,?,?,?,?,?,?)";
Object[] params = { order.getOid(), order.getOrdertime(), order.getTotal(),
order.getState(),order.getAddress(), order.getName(),
order.getTelephone(), order.getUser().getUid() };
queryRunner.update(conn, sql, params);
}
@Override
public void save(Connection conn, OrderItem orderItem) throws SQLException{
QueryRunner queryRunner = new QueryRunner();
String sql = "insert into orderitem values (?,?,?,?,?)";
Object[] params = { orderItem.getItemid(), orderItem.getCount(),
orderItem.getSubtotal(),orderItem.getProduct().getPid(),
orderItem.getOrder().getOid() };
queryRunner.update(conn, sql, params);
}
}