前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Web-第二十二天 Web商城实战二【悟空教程】

Web-第二十二天 Web商城实战二【悟空教程】

作者头像
Java帮帮
发布2018-07-27 15:04:26
1.1K0
发布2018-07-27 15:04:26
举报

Web-第二十二天 Web商城实战二【悟空教程】

Web商城实战二

今日内容介绍

  • 分类管理:查询所有分类
  • 商品管理
  • 购物车模块
  • 订单模块

今日内容学习目标

  • JavaWeb知识巩固

第1章 查询所有分类

1.1 分析

1.2 准备工作

  • 创建数据库表、JavaBean、Dao接口和实现类、Service接口和实现类
  • 步骤1:创建分类表

-- 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','汽车用品');

  • 步骤2:创建JavaBean Category

public class Category {

private String cid;

private String cname;

  • 步骤3:编写dao接口、及实现类

/**

* 分类模块dao层的接口

*

*/

public interface CategoryDao {

}

/**

* 分类模块dao层的实现类

*

*/

public class CategoryDaoImpl implements CategoryDao {

}

  • 步骤4:编写service即可及实现类

/**

* 分类模块service层的接口

*

*/

public interface CategoryService {

}

package cn.com.javahelp.store.service.impl;

/**

* 分类模块service层的接口

*/

public class CategoryServiceImpl implements CategoryService {

}

活着(2017年新版)

作者:余华

当当 广告

购买

1.3 代码实现

  • 步骤1:完善IndexServlet,显示/jsp/index.jsp前查询分类

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";

}

}

  • 步骤2:完善CategoryService,提供findAll()方法

//接口

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();

}

}

  • 步骤3:完善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));

}

}

  • 步骤4:遍历数据

<%--激活 <li> --%>

<c:forEach items="${allCategory}" var="category">

<li value="${category.cid}"><a href="#">${category.cname}</a></li>

</c:forEach>

1.4 优化:Ajax异步加载

1.4.1 分析

当访问首页时可以显示分类导航条,但访问其他模块时无法访问显示分类。通过比较程序我们发现,显示首页前我们查询了所有分类,显示登录等其他模块时我们没有查询分类。为了所有模块都可以显示分类,我们需要发送ajax单独查询分类。

1.4.2 代码实现

  • 步骤1:修改IndexServlet,将查询分类代码注释
  • 步骤2:修改header.jsp 给<ul>添加id,并注释查询所有的遍历内容
  • 步骤3:修改header.jsp 添加js函数,页面加载发送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>

  • 步骤4:编写CategoryServlet,提供findAll()方法

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;

}

}

  • 步骤5:web.xml servlet的配置

<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>

1.5 增强:缓存技术

1.5.1 分析

当我们在不同模块之间切换时,发现菜单栏显示的分类数据都是一样的。浏览器每发送一次请求,服务器端都会查询一次数据库,从而对数据库服务器造成不必要的访问。实际开发中,我们采用缓存技术来解决此类问题。

1.5.2 相关技术

  • 缓存(Cache):通常指的就是内存中的一块空间,介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。
  • 常见的缓存技术
    • redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多。
    • Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。
    • EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点。
  • 导入jar包:

1.5.3 代码实现

  • 如果缓存中已经有,将直接从缓存获得,如果没有将从数据库获取。修改CategoryService代码,给当前查询所有添加业务缓存。

/**

* 查询分类通过缓存服务器

*/

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);

}

}

1.5.4 Redis工具类

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();

}

}

}

第2章 前台商品管理

2.1 准备工作

  • 步骤1:创建表并完善数据

-- 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')

参考:

  • 步骤2:编写JavaBean Product

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;

  • 步骤3:编写dao接口,及实现类

/**

* 商品dao接口

*/

public interface ProductDao {

}

/**

* 商品dao实现类

*/

public class ProductDaoImpl implements ProductDao {

}

  • 步骤4:编写service接口,及实现类

/**

* 商品service接口

*/

public interface ProductService {

}

/**

* 商品service实现类

*/

public class ProductServiceImpl implements ProductService {

}

  • 步骤5:编写servlet

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>

2.2 首页热门商品和最新商品的显示

2.2.1 分析

2.2.2 代码实现

  • 步骤1:修改IndexServlet,添加查询热门和最新商品的查询

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";

}

}

  • 步骤2:修改service,提供findByHot()和findByNew()方法

// 接口

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();

}

}

  • 步骤3:修改dao,提供findByHot()和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;

}

}

  • 步骤4:修改/jsp/index.jsp,页面显示

<%--热门商品列表 --%>

<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>

2.3 商品详情

2.3.1 分析

2.3.2 代码实现

  • 步骤1:修改/jsp/index.jsp,点击图片或标题可以查询商品详情
  • 步骤2:修改ProductServlet,添加findById方法

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";

}

}

  • 步骤3:修改ProductService,添加findById()方法

//接口

/**

* 通过id查询详情

* @param pid

* @return

*/

Product findById(String pid) throws SQLException

//实现类

@Override

public Product findById(String pid) throws SQLException {

return productDao.findById(pid);

}

  • 步骤4:修改ProductDao,添加findById()方法

//接口

/**

* 通过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;

}

  • 步骤 5:修改product_info.jsp,显示信息

2.4 查询分类商品(含分页)

2.4.1 分析

2.4.2 代码实现

  • 步骤1:修改/jsp/header.jsp 显示分类列表的js代码

//支持分页,如果没有传递默认值1

$("#menu").append("<li value=''><a href='${pageContext.request.contextPath}/ProductServlet?method=findByCid&cid="+n.cid+"'>"+n.cname+"</a></li>");

  • 步骤2:修改ProductServlet,添加findByCid方法

//通过分类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";

}

  • 步骤3:编写PageBean对象

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;

}

  • 步骤4:修改ProductService,添加findByCid()方法

//接口

/**

* 分页查询所有商品

* @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;

}

  • 步骤5:修改ProductDao,提供 findTotalRecordByCid() 和 findAllByCid()

//接口

/**

* 查询总记录(含分页)

* @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;

}

  • 步骤6:修改/jsp/product_list.jsp页面,显示数据

<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>

  • 步骤7:分页条

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>

第3章 作业

3.1 浏览历史记录

3.1.1 分析

3.1.2 代码实现

  • 步骤1:修改ProductServlet的findById方法,使用cookie记录商品id,以“-”拼凑。

/**浏览历史记录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*/

  • 步骤2:修改product_list.jsp ,显示历史记录

<%

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>

<%

}

}

%>

第4章 购物模块

4.1 需求

昨天我们已经完成商品信息的查询,接着将允许用户通过商城进行商品的购买。通过浏览器访问商城,就相当于去超市购买商品,我们需要使用“购物车”对准备购买商品的增删操作。

4.2 分析

4.3 准备工作

  • 购物项 CartItem对象

/**

* 购物项的实体:用于封装某一类商品的购买情况

*/

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;

}*/

}

  • 购物车 Cart对象

/**

* 购物车的对象

*/

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;

}

}

4.4 代码实现

4.4.1 添加商品到购物车

  • 步骤1:商品详情时,点击“添加到购物车”,将当前商品和购买数量以表单方式发送给服务器,表单主体如下:

<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>

  • 步骤2:编写CartServlet

//实现类

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>

  • 步骤3:给CartServlet 添加 addToCart()方法

// 添加商品到购物车

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;

}

  • 步骤4:jsp页面显示信息

<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>

4.4.2 清空购物车

  • 步骤1:购物车cart.jsp页面,点击“清空购物车”

<a href="${pageContext.request.contextPath}/CartServlet?method=clearCart" id="clear">清空购物车</a>

  • 步骤2:修改CartServlet,添加clearCart()方法

// 清空购物车

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;

}

  • 步骤3:完善cart.jsp页面,如果购物车为空,显示“您暂时没有购买任何商品”

<c:if test="${empty cart || empty cart.cartItems }">

您还没有购买任何商品

</c:if>

<c:if test="${not (empty cart || empty cart.cartItems) }">

//购物车代码

</c:if>

4.4.3 移除购物项

  • 步骤1:在购物车页面,点击“删除”

<a href="${pageContext.request.contextPath}/CartServlet?method=removeCart&pid=${cartItem.product.pid}">删除</a>

  • 步骤2:修改CartServlet,添加removeCart

// 从购物车移除商品

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;

}

第5章 订单模块

5.1 需求

用户已经可以成功将商品添加到购物车,接着我们将进行订单操作,将准备购买的商品变成已购买的商品。

5.2 分析

5.3 准备工作

  • 步骤1:创建表

-- 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;

  • 步骤2:编写JavaBean

/**

* 订单的实体

* 实体中定义的属性 尽量使用包装类的类型.

* * 基本数据类型默认值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; // 订单项属于哪个订单

  • 步骤3:编写dao接口和实现

/**

* 订单dao接口

*/

public interface OrderDao {

}

/**

* 订单dao实现类

*/

public class OrderDaoImpl implements OrderDao {

}

  • 步骤4:编写service接口和实现

/**

* 订单service接口

*/

public interface OrderService {

}

/**

* 订单service实现类

*/

public class OrderServiceImpl implements OrderService {

}

  • 步骤5:编写OrderServlet实现类

public class OrderServlet extends BaseServlet {

private static final long serialVersionUID = 1L;

}

  • 步骤6:编写OrderServlet配置

<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>

5.4 代码实现

  • 步骤1:在购物车页面,点击“提交订单”

<a href="${pageContext.request.contextPath}/OrderServlet?method=saveOrder">提交订单

  • 步骤2:修改OrderServlet,添加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";

}

  • 步骤3:修改OrderService,添加addOrder(order);

//接口

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();

}

}

}

  • 步骤4:修改OrderDao,添加 save(order)和save(orderItem)

//接口

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);

}

}

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java帮帮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Web商城实战二
  • 第1章 查询所有分类
    • 1.1 分析
      • 1.2 准备工作
        • 活着(2017年新版)
          • 1.3 代码实现
            • 1.4 优化:Ajax异步加载
              • 1.4.1 分析
              • 1.4.2 代码实现
            • 1.5 增强:缓存技术
              • 1.5.1 分析
              • 1.5.2 相关技术
              • 1.5.3 代码实现
              • 1.5.4 Redis工具类
          • 第2章 前台商品管理
            • 2.1 准备工作
              • 2.2 首页热门商品和最新商品的显示
                • 2.2.1 分析
                • 2.2.2 代码实现
              • 2.3 商品详情
                • 2.3.1 分析
                • 2.3.2 代码实现
              • 2.4 查询分类商品(含分页)
                • 2.4.1 分析
                • 2.4.2 代码实现
            • 第3章 作业
              • 3.1 浏览历史记录
                • 3.1.1 分析
                • 3.1.2 代码实现
            • 第4章 购物模块
              • 4.1 需求
                • 4.2 分析
                  • 4.3 准备工作
                    • 4.4 代码实现
                      • 4.4.1 添加商品到购物车
                      • 4.4.2 清空购物车
                      • 4.4.3 移除购物项
                  • 第5章 订单模块
                    • 5.1 需求
                      • 5.2 分析
                        • 5.3 准备工作
                          • 5.4 代码实现
                          相关产品与服务
                          数据保险箱
                          数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档