JavaWeb书城项目(三)
- 7、购物车
- 7.1、购物车模块分析
- 7.2、购物车模型编写
- 7.3、加入购物车功能的实现
- 7.4、购物车的展示
- 7.5、删除购物车商品项
- 7.6、清空购物车
- 7.7、修改购物车商品数量
- 7.8、 首页,购物车数据回显
- 8、订单
- 8.1、订单模块的分析
- 8.2、创建订单模块的数据库表
- 8.3、创建订单模块的数据模型
- 8.4、编写订单模块的 Dao 程序
- 8.5、编写订单模块的 Service
- 8.6、编写订单模块的 web 层和页面联调
7、购物车
7.1、购物车模块分析
( 注意: 本模块中讲解的是将购物车信息保存到 session 域中,不涉及到数据库,也就没有 DAO 层、Service 层)
购物车模型可以参考分页的时候的 Page 模型
首先要有一个 购物车对象 Cart ,包含以下部分:
- totalCount:总商品数量
- totalPrice:购物车商品总金额
- items:购物车的商品,是一个集合,里面包含商品项对象 CartItem
但是对于 items 这里和分页模型有些许不同,分页里面只需要把具体的商品对象列出来即可,但是购物车这里要显示商品的订购数量
所以还要有一个购物车商品项对象 CartItem ,包含如下内容:
- id:商品编号
- name:商品名称
- count:商品数量
- price:商品单价
- totalPrice:单类商品总价
购物车部分类似于分页部分,可以被应用到各个地方
分析购物车的功能 web 层:
- 加入购物车
addItem() - 删除商品项,删除整个类别的商品
deleteItem() - 清空购物车
clear() - 修改购物车中商品数量
updateCount()
由于本模块没有 Service 层、DAO 层,所以上面的方法声明在 购物车对象 Cart 里面
- addItem( CartItem ) 添加商品项
- deleteItem( id ) 删除商品项
- clear() 清空购物车
- updateCount( id ,count ) 修改商品数量
结账的功能一般属于订单模块,因为要生成订单列表
每个模块都有自己的 servlet 程序,所以这里要新建 CartServlet ,继承于 BaseServlet
7.2、购物车模型编写
购物车商品项对象 CartItem
public class CartItem {
private Integer id;
private String name;
private Integer count;
private BigDecimal price;
private BigDecimal totalPrice;
}
购物车对象 Cart
注意:此类中不需要生成构造器,因为后面不会被使用,只需要生成 get、set、toString() 方法
还要注意,对于 totalCount、totalPrice 这两个属性不应该被赋值,应该是从 items 的所有商品的总金额、总数量累加得来,所以注意这两个属性只可以有 get() 方法,没有 set() 方法
注意要更改toString()
方法,不然无法无法更新到这两个值
而在get()
方法里面,需要先给一个初始值,不然调用的时候会报空指针异常
既然在方法里面给了初始值,不防就不显式的定义这两个属性,直接只提供两个 get() 方法
public class Cart {
//private Integer totalCount;
//private BigDecimal totalPrice;
//private List<CartItem> items = new ArrayList<>();
//为方便确认集合里面的购物车商品项对象是否已经存在,items 可以设置为 Map 键值对式
//key 为 CartItem 的 id 商品编号,value 为 CartItem 对象
private Map<Integer,CartItem> items = new LinkedHashMap<>();
public Integer getTotalCount() {
//要先初始化值,不然会有空指针异常
Integer totalCount = 0;
for (CartItem cartItem : items.values()) {
totalCount += cartItem.getCount();
}
return totalCount;
}
public BigDecimal getTotalPrice() {
//要先初始化值,不然会有空指针异常
BigDecimal totalPrice = new BigDecimal(0);
for (CartItem cartItem : items.values()) {
totalPrice = totalPrice.add(cartItem.getTotalPrice());
}
return totalPrice;
}
@Override
public String toString() {
return "Cart{" +
"totalCount=" + getTotalCount() +
", totalPrice=" + getTotalPrice() +
", items=" + items +
'}';
}
}
在购物车对象 Cart 中声明方法,完成增删改清空的操作
1、addItem( CartItem ) 添加商品项
注意在添加购物车的时候,要先查看购物车中是否已经添加过此商品
如果已添加,那就只需要让数量累加、总金额更新;
如果没添加过,才在集合中添加元素
而为了更好地在 items 里面根据 CartItem 的 id 判断是否已经存在,items 就定义为 Map 键值对式,key 为 CartItem 的 id ,value 为 CartItem 对象
如果 items 定义为 List 类型,那么判断是否存在还需要对集合进行遍历
public class Cart {
//添加商品项
public void addItem(CartItem cartItem){
//查看购物车中是否已经存在此商品
CartItem ci = items.get(cartItem.getId());
if(ci == null){
//之前没有添加过
items.put(cartItem.getId(),cartItem);
}else{
//已经添加过的情况,购物车中商品项对象的数量、总金额需要变化
ci.setCount(ci.getCount() + 1);
//总金额 = 新的数量 * 单价
//涉及到财务数据,使用 BigDecimal 中的 multiply 乘法,里面需要传入BigDecimal类型
ci.setTotalPrice(ci.getPrice().multiply(new BigDecimal(ci.getCount())));
}
}
}
2、deleteItem( id) 删除商品项
public class Cart {
//删除商品项
public void deleteItem(Integer id){
items.remove(id);
}
}
3、clear() 清空购物车
public class Cart {
//清空购物车
public void clear(){
items.clear();
}
}
4、updateCount( id ,count ) 修改商品数量
先查看购物车中是否已经存在此商品,如果有,就修改商品数量,更新总金额
public class Cart {
//修改商品数量
public void updateCount(Integer id,Integer count){
//查看购物车中是否已经存在此商品
CartItem cartItem = items.get(id);
if(cartItem != null){
//已经存在此商品,修改商品项的数量、总金额
cartItem.setCount(count); //修改商品数量
cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount()))); //修改商品总金额
}
}
}
7.3、加入购物车功能的实现
因为添加商品进购物车,需要用到商品编号
在按钮部分,将当前操作的图书的编号封装进自定义属性
在单击事件中获取到商品的编号,使用 jQuery 的方法 attr()
,传入一个参数是获取属性值,传入两个参数就是设置属性的值
注意,这里获取 id 值的时候,一定是 ${this}
的对象来获取的,在事件响应的 function 函数 中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象
$(function () {
//加入购物车按钮,绑定单击事件
$("button.addToCart").click(function () {
//在单击事件中获取到商品的编号
// 使用 attr(),传入一个参数是获取属性值,传入两个参数就是设置属性的值
//在事件响应的 function 函数 中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象
var bid = $(this).attr("bbid");
//basePath 是动态base标签部分定义的变量,在分页中 跳转到指定页数 也用到过
location.href = "${basePath}cartServlet?methodName=addItem&id=" + bid;
})
})
如果是像下图一样,使用 class 属性来定位 按钮标签
那么获取到的编号 id 永远是 1
CartServlet 程序中的步骤:
- 获取请求的参数:商品编号
- 调用 BookServiceImpl.queryBookById() ,得到图书信息
- 根据图书信息,生成购物车商品项对象 CartItem
- 调用 Cart.addItem(cartItem) ,添加商品项
注意,这里需要创建 Cart 对象,但若是每次点击 “ 加入购物车 ”都会重建新的 Cart 对象的话,那么购物车的东西永远都多不起来,所以需要判断
本项目是将购物车信息保存到 session 域中 - 请求重定向回到商品列表
回到商品列表的时候需要回到当时点击按钮的那一页
此时第一反应是想得到按钮所在的当前页对象,并将其作为请求参数发给 CartServlet 程序
但在 HTTP 协议中有个请求头 Referer ,它会在请求发起的时候(点击按钮的时候),将浏览器的地址发送给服务器,那么我们只需要拿到这个地址,然后请求重定向回到这个地址即可
public class CartServlet extends BaseServlet {
private BookServiceImpl bookService = new BookServiceImpl();
//加入购物车
public void addItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数:商品编号,本项目中也就是图书编号
int id = WebUtils.parseInt(request.getParameter("id"), 0);
//调用 BookServiceImpl.queryBookById() ,得到图书信息
Book book = bookService.queryBookById(id);
//根据图书信息,生成购物车商品项对象 CartItem
CartItem cartItem = new CartItem(book.getId(), book.getName(), 1, book.getPrice(), book.getPrice());
//调用 Cart.addItem(cartItem) ,添加商品项
//注意这里,每次都创建新的购物车的话,里面的内容就没法都保存下来
// Cart cart = new Cart();
//本项目讲解的是将购物车信息保存到 session 域中
//保证每次使用的都是一个购物车,不是每次请求添加就都是新的购物车
Cart cart = (Cart) request.getSession().getAttribute("cart");
if(cart == null){
cart = new Cart();
request.getSession().setAttribute("cart",cart);
}
cart.addItem(cartItem);
//请求重定向回到商品列表中按钮点击发起请求的页面
response.sendRedirect(request.getHeader("Referer"));
}
}
注意:
- 本项目是将购物车信息 Cart 对象保存到 session 域中
- 使用请求头信息 Referer ,来获取请求发起时候的地址,最后请求重定向回到该地址
7.4、购物车的展示
需要在购物车页面展示购物车商品信息,一般在 jsp 页面使用数据的时候,就要想到使用 Servlet 程序处理数据,然后请求转发到 jsp 页面中
但是本项目在此处,在进行添加操作的时候,已经将购物车对象放进了 session 域中,所以展示购物车商品信息不需要经过 Servlet 程序,直接获取 session 域中数据 ${sessionScope.cart}
在购物车页面下方的去结账超链接部分,如果购物车没有数据就不显示,判断一下 session 域中的 items 是否为空即可
购物车没有数据,在页面显示提示信息【亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!】
<table>
<tr>
<td>商品名称</td>
<td>数量</td>
<td>单价</td>
<td>金额</td>
<td>操作</td>
</tr>
<%--如果购物车空的情况--%>
<c:if test="${empty sessionScope.cart.items}">
<tr>
<%--跨列表格--%>
<td colspan="5"><a href="${basePath}">亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!</a></td>
</tr>
</c:if>
<%--如果购物车非空的情况--%>
<c:if test="${not empty sessionScope.cart.items}">
<%--使用 JSTL 标签对 Map 进行遍历--%>
<c:forEach items="${sessionScope.cart.items}" var="entry">
<tr>
<td>${entry.value.name}</td>
<td>${entry.value.count}</td>
<td>${entry.value.price}</td>
<td>${entry.value.totalPrice}</td>
<td><a class="deletefromcart" href="cartServlet?methodName=deleteItem&id=${entry.value.id}">删除</a></td>
</tr>
</c:forEach>
</c:if>
</table>
<%--如果购物车非空才输出页面的内容--%>
<c:if test="${not empty sessionScope.cart.items}">
<div class="cart_info">
<span class="cart_span">购物车中共有<span class="b_count">${sessionScope.cart.totalCount}</span>件商品</span>
<span class="cart_span">总金额<span class="b_price">${sessionScope.cart.totalPrice}</span>元</span>
<span class="cart_span"><a href="#">清空购物车</a></span>
<span class="cart_span"><a href="pages/cart/checkout.jsp">去结账</a></span>
</div>
</c:if>
7.5、删除购物车商品项
CartServlet 程序
public class CartServlet extends BaseServlet {
private BookServiceImpl bookService = new BookServiceImpl();
//删除购物车商品项
protected void deleteItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取请求的参数:商品编号,本项目中也就是图书编号
int id = WebUtils.parseInt(request.getParameter("id"), 0);
//获取前购物车信息
Cart cart = (Cart) request.getSession().getAttribute("cart");
if(cart != null){
cart.deleteItem(id);
}
//请求重定向回到商品列表中按钮点击发起请求的页面
response.sendRedirect(request.getHeader("Referer"));
}
}
购物车/pages/cart/cart.jsp 页面的代码:
删除的请求地址:
删除的确认提示操作:
<script type="text/javascript">
$(function () {
//给删除超链接绑定单击事件,用于弹出提示信息
$("a.deletefromcart").click(function () {
return confirm("确定删除【"+$(this).parent().parent().children("td").first().text()+"】吗?")
})
})
</script>
7.6、清空购物车
CartServlet 程序
public class CartServlet extends BaseServlet {
private BookServiceImpl bookService = new BookServiceImpl();
//清空购物车
protected void clear(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取前购物车信息
Cart cart = (Cart) request.getSession().getAttribute("cart");
if(cart != null){
cart.clear();
}
//请求重定向回到商品列表中按钮点击发起请求的页面
response.sendRedirect(request.getHeader("Referer"));
}
}
cart.jsp 页面的内容
给清空购物车添加请求地址,和添加 id 属性:
清空的确认提示操作:
<script type="text/javascript">
$(function () {
//给清空购物车绑定单击事件
$("#clearcart").click(function () {
return confirm("你确定要清空购物车吗?")
})
})
</script>
7.7、修改购物车商品数量
CartServlet 程序
public class CartServlet extends BaseServlet {
private BookServiceImpl bookService = new BookServiceImpl();
//修改购物车商品数量
protected void updateCount(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int id = WebUtils.parseInt(request.getParameter("id"), 0);
int count = WebUtils.parseInt(request.getParameter("count"), 1);
//获取前购物车信息
Cart cart = (Cart) request.getSession().getAttribute("cart");
if(cart != null){
cart.updateCount(id,count);
}
//请求重定向回到商品列表中按钮点击发起请求的页面
response.sendRedirect(request.getHeader("Referer"));
}
}
修改 pages/cart/cart.jsp 购物车页面
修改商品数量 js 代码:
给数量的输入框绑定事件,来实现输入数量之后,鼠标移向其他地方,数量的修改就生效
第一可能考虑到 失去焦点事件,但是需要判断用户输入的数量与之前的数量相比是否有变化,没有变化就不需要进行修改
所以这里使用 内容发生改变事件,当输入框的内容发生改变的时候,就触发事件
$(".updateCount").change(function () {
var name = $(this).parent().parent().find("td:first").text();
var count = $(this).val();
var bbbid = $(this).attr("bbbid");
if(confirm("你确定要修改【"+ name +"】的数量为【"+ count +"】吗?")){
location.href = "${basePath}cartServlet?methodName=updateCount&count="+count+"&id="+bbbid;
}else {
//用户不想更换数量,让输入框还原到之前的数字
// defaultValue 属性是表单项 Dom 对象的属性。它表示默认的 value 属性
this.value = this.defaultValue;
}
})
7.8、 首页,购物车数据回显
在添加商品到购物车的时候,保存最后一个添加的商品名称:
在 pages/client/index.jsp 页面中输出购物车信息:
判断一下购物车是否为空
<div style="text-align: center">
<%--购物车为空的输出--%>
<c:if test="${empty sessionScope.cart.items}">
<span> </span>
<div>
<span style="color: red">当前购物车为空</span>
</div>
</c:if>
<%--购物车非空的输出--%>
<c:if test="${not empty sessionScope.cart.items}">
<span>您的购物车中有${sessionScope.cart.totalCount}件商品</span>
<div>
您刚刚将<span style="color: red">${sessionScope.cartItemName}</span>加入到了购物车中
</div>
</c:if>
</div>
8、订单
8.1、订单模块的分析
后台管理有管理订单页面
前台用户有我的订单页面
分析订单的功能,然后一个功能对于着 Servlet 程序里面的一个方法
Servlet 程序李曼的方法对应着 Service 层里面的方法
Service 层里面的方法需要使用数据库的地方,就用到 DAO
DAO 层是一个 JavaBean,对应着一个 DAO
(所以本模块中有两个 DAO )
8.2、创建订单模块的数据库表
use book;
create table t_order(
`order_id` varchar(50) primary key,
`create_time` datetime,
`price` decimal(11,2),
`status` int,
`user_id` int,
foreign key(`user_id`) references t_user(`id`)
);
create table t_order_item(
`id` int primary key auto_increment,
`name` varchar(100),
`count` int,
`price` decimal(11,2),
`total_price` decimal(11,2),
`order_id` varchar(50),
foreign key(`order_id`) references t_order(`order_id`)
);
8.3、创建订单模块的数据模型
由订单的界面,分析订单的模型:
一个对应订单的管理,需要创建 JavaBean、数据库
一个对应订单内部详情,包含着商品信息,需要创建 JavaBean、数据库
public class Order {
//订单编号
private String orderId;
//订购时间
private Date createTime;
//发货状态:0 未发货,1 已发货,2 表示已签收
private Integer status = 0;
//用户编号
private Integer userId;
private BigDecimal price;
}
public class OrderItem {
private Integer id;
//订单编号
private String orderId;
//单价
private BigDecimal price;
//总价
private BigDecimal totalPrice;
private String name;
private Integer count;
}
8.4、编写订单模块的 Dao 程序
DAO 层是一个 JavaBean,对应着一个 DAO
(所以本模块中有两个 DAO )
OrderDAO 接口
public interface OrderDAO {
//生成订单的时候,将信息保存到数据库中
void saveOrder(Order order);
//用户查询订单
List<Order> queryOrderByUserId(int userId);
//根据订单号查询订单
Order queryOrderByOrderId(String orderId);
//查看所有订单
List<Order> queryAllOrder();
//更改发货状态
void changeOrderStatus(String orderId,int newStatus);
}
OrderDAO 实现
public class OrderDAOImpl extends BaseDAO<Order> implements OrderDAO{
@Override
public void saveOrder(Order order) {
//生成订单的时候,将信息保存到数据库中
Connection conn = jdbcUtils.getconn();
String sql = "INSERT INTO `t_order`(`order_id`,`create_time`,`price`,`status`,`user_id`) VALUES(?,?,?,?,?);";
update(conn,sql,order.getOrderId(),order.getCreateTime(),order.getPrice(),order.getStatus(),order.getUserId());
jdbcUtils.close(conn);
}
@Override
public List<Order> queryOrderByUserId(int userId) {
//用户查询订单
Connection conn = jdbcUtils.getconn();
String sql = "SELECT `order_id` orderId,`create_time` createTime,`price`,`status`,`user_id` userId FROM `t_order` WHERE `user_id` = ?;";
List<Order> orders = queryForList(conn, sql, userId);
jdbcUtils.close(conn);
return orders;
}
@Override
public Order queryOrderByOrderId(String orderId) {
//根据订单号查询订单
Connection conn = jdbcUtils.getconn();
String sql = "SELECT `order_id` orderId,`create_time` createTime,`price`,`status`,`user_id` userId FROM `t_order` WHERE `order_id` = ?;";
Order order = queryForOne(conn, sql, orderId);
jdbcUtils.close(conn);
return order;
}
@Override
public List<Order> queryAllOrder() {
//查看所有订单
Connection conn = jdbcUtils.getconn();
String sql = "SELECT `order_id` orderId,`create_time` createTime,`price`,`status`,`user_id` userId FROM `t_order`;";
List<Order> orders = queryForList(conn, sql);
jdbcUtils.close(conn);
return orders;
}
@Override
public void changeOrderStatus(String orderId, int newStatus) {
//更改发货状态
Connection conn = jdbcUtils.getconn();
String sql = "UPDATE `t_order` SET `status`=? WHERE `order_id`=?;";
update(conn,sql,newStatus,orderId);
jdbcUtils.close(conn);
}
}
OrderItemDAO 接口
public interface OrderItemDAO {
//生成订单的时候,将信息保存到数据库中
void saveOrderItem(OrderItem orderItem);
//查看订单详情
List<OrderItem> queryOrderItem(String orderId);
}
OrderItemDAO 实现
public class OrderItemDAOImpl extends BaseDAO<OrderItem> implements OrderItemDAO {
@Override
public void saveOrderItem(OrderItem orderItem) {
//生成订单的时候,将信息保存到数据库中
Connection conn = jdbcUtils.getconn();
String sql = "INSERT INTO `t_orderitem`(`name`,`count`,`price`,`total_price`,`order_id`) VALUES(?,?,?,?,?);";
update(conn,sql,orderItem.getName(),orderItem.getCount(),orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId());
jdbcUtils.close(conn);
}
@Override
public List<OrderItem> queryOrderItem(String orderId) {
//查看订单详情
Connection conn = jdbcUtils.getconn();
String sql = "SELECT `id`,`name`,`count`,`price`,`total_price` totalPrice,`order_id` orderId FROM `t_orderitem` WHERE `order_id`=?;";
List<OrderItem> orderItems = queryForList(conn, sql, orderId);
jdbcUtils.close(conn);
return orderItems;
}
}
8.5、编写订单模块的 Service
OrderService 接口
public interface OrderService {
//生成订单,返回订单号
String createOrder(Cart cart, Integer userId);
//查询所有订单
List<Order> showAllOrders();
//管理员发货
void sendOrder(String orderId);
//查看订单详情
List<OrderItem> queryOrderDetail(String orderId);
//用户查看我的所有订单
List<Order> showMyOrders(Integer userId);
//用户签收订单
void receiveOrder(String orderId);
}
OrderService 实现类
public class OrderServiceImpl implements OrderService {
private OrderDAOImpl orderDAOImpl= new OrderDAOImpl();
private OrderItemDAOImpl orderItemDAOImpl= new OrderItemDAOImpl();
@Override
public String createOrder(Cart cart, Integer userId) {
//生成订单,返回订单号
// 订单号 ===> 唯一性
String orderId = System.currentTimeMillis()+""+userId;
Order order = new Order(orderId,new Date(),0,userId,cart.getTotalPrice());
orderDAOImpl.saveOrder(order);
for (CartItem cartItem : cart.getItems().values()) {
OrderItem orderItem = new OrderItem(null,orderId,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice());
orderItemDAOImpl.saveOrderItem(orderItem);
//当购物车的数据生成订单之后,商品的销量和库存要发生变化
Book book = new BookServiceImpl().queryBookById(cartItem.getId());
book.setSales(book.getSales() + cartItem.getCount());
book.setStock(book.getStock() - cartItem.getCount()); //应该要在某处判断订购的数量不会超过库存数量
//BookServiceImpl 是 Book 的service层,执行更新的结果是变动数据库的数据
new BookServiceImpl().updateBook(book);
}
//当购物车的数据生成订单之后,要清空购物车
cart.clear();
return orderId;
}
@Override
public List<Order> showAllOrders() {
//查询所有订单
List<Order> orders = orderDAOImpl.queryAllOrder();
return orders;
}
@Override
public void sendOrder(String orderId) {
//管理员发货
//判断发货状态
Order order = orderDAOImpl.queryOrderByOrderId(orderId);
if(order.getStatus() == 0){
orderDAOImpl.changeOrderStatus(orderId,1);
System.out.println("管理员发货成功");
}else {
System.out.println("管理员发货失败,订单发货状态异常");
}
}
@Override
public List<OrderItem> queryOrderDetail(String orderId) {
//查看订单详情
List<OrderItem> orderItems = orderItemDAOImpl.queryOrderItem(orderId);
return orderItems;
}
@Override
public List<Order> showMyOrders(Integer userId) {
//用户查看我的所有订单
List<Order> orders = orderDAOImpl.queryOrderByUserId(userId);
return orders;
}
@Override
public void receiveOrder(String orderId) {
//用户签收订单
//判断发货状态
Order order = orderDAOImpl.queryOrderByOrderId(orderId);
if(order.getStatus() == 1){
orderDAOImpl.changeOrderStatus(orderId,2);
System.out.println("用户签收成功");
}else {
System.out.println("用户签收失败,订单发货状态异常");
}
}
}
8.6、编写订单模块的 web 层和页面联调
如果直接请求重定向的地址如下:
response.sendRedirect("/pages/user/login.jsp");
则页面显示如下:
缺少工程名
所以应该是:
response.sendRedirect(request.getContextPath()+"/pages/user/login.jsp");
OrderServlet 程序:
public class OrderServlet extends BaseServlet {
private OrderServiceImpl orderServiceImpl = new OrderServiceImpl();
//生成订单
protected void createOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cart cart = (Cart) request.getSession().getAttribute("cart");
User user = (User) request.getSession().getAttribute("user");
//如果用户没有登录,跳转到登录页面
if(user == null){
response.sendRedirect(request.getContextPath()+"/pages/user/login.jsp");
//页面跳转之后就不可以再执行其他语句
return;
}
String orderId = orderServiceImpl.createOrder(cart, user.getId());
//如果这里使用请求转发,那么当 F5 刷新浏览器的时候,又会执行一遍 “ 生成订单 ” 操作
// request.setAttribute("orderId",orderId);
// request.getRequestDispatcher("/pages/cart/checkout.jsp").forward(request,response);
request.getSession().setAttribute("orderId",orderId);
response.sendRedirect(request.getContextPath()+"/pages/cart/checkout.jsp");
}
//查询所有订单
protected void showAllOrders(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<Order> orders = orderServiceImpl.showAllOrders();
request.setAttribute("AllOrders",orders);
request.getRequestDispatcher("/pages/manager/order_manager.jsp").forward(request,response);
}
//管理员发货
protected void sendOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
orderServiceImpl.sendOrder(request.getParameter("orderId"));
response.sendRedirect(request.getContextPath()+"/orderServlet?methodName=showAllOrders");
}
//查看订单详情
protected void queryOrderDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
List<OrderItem> orderItem = orderServiceImpl.queryOrderDetail(request.getParameter("orderId"));
request.setAttribute("orderItem",orderItem);
request.getRequestDispatcher("/pages/order/order_items.jsp").forward(request,response);
}
//用户查看我的所有订单
protected void showMyOrders(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
User user = (User) request.getSession().getAttribute("user");
//如果用户没有登录,跳转到登录页面
if(user == null){
response.sendRedirect(request.getContextPath()+"/pages/user/login.jsp");
//页面跳转之后就不可以再执行其他语句
return;
}
List<Order> orders = orderServiceImpl.showMyOrders(user.getId());
request.setAttribute("MyOrders",orders);
request.getRequestDispatcher("/pages/order/order.jsp").forward(request,response);
}
//用户签收订单
protected void receiveOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
orderServiceImpl.receiveOrder(request.getParameter("orderId"));
response.sendRedirect(request.getContextPath()+"/orderServlet?methodName=showMyOrders");
}
}
修改 pages/cart/cart.jsp 页面,结账的请求地址:
修改 pages/cart/checkout.jsp 页面,输出订单号:
修改 pages/common/manager_menu.jsp 页面,订单管理的请求地址:
修改 pages/manager/order_manager.jsp 页面,查询所有订单:
<table>
<tr>
<td>日期</td>
<td>金额</td>
<td>详情</td>
<td>发货</td>
</tr>
<c:forEach items="${requestScope.AllOrders}" var="order">
<tr>
<td>${order.createTime}</td>
<td>${order.price}</td>
<td><a href="orderServlet?methodName=queryOrderDetail&orderId=${sessionScope.orderId}">查看详情</a></td>
<c:choose>
<c:when test="${order.status == 0}">
<td><a href="orderServlet?methodName=sendOrder&orderId=${sessionScope.orderId}">点击发货</a></td>
</c:when>
<c:when test="${order.status == 1}">
<td>已发货</td>
</c:when>
<c:when test="${order.status == 2}">
<td>已签收</td>
</c:when>
</c:choose>
</tr>
</c:forEach>
</table>
上面页面中的,管理员发货:
修改 pages/manager/order_manager.jsp 页面,修改 pages/order/order.jsp 页面,查看订单详情:
修改 pages/client/index.jsp 页面,我的订单的请求地址:
修改 pages/common/welcome_menu.jsp 页面,我的订单的请求地址:
修改 pages/order/order.jsp 页面,我的订单页面:
<table>
<tr>
<td>日期</td>
<td>金额</td>
<td>状态</td>
<td>详情</td>
</tr>
<c:forEach items="${requestScope.MyOrders}" var="order">
<tr>
<td>${order.createTime}</td>
<td>${order.price}</td>
<c:choose>
<c:when test="${order.status == 0}">
<td>未发货</td>
</c:when>
<c:when test="${order.status == 1}">
<td><a href="orderServlet?methodName=receiveOrder&orderId=${sessionScope.orderId}">已发货,点击签收</a></td>
</c:when>
<c:when test="${order.status == 2}">
<td>已签收</td>
</c:when>
</c:choose>
<td><a href="orderServlet?methodName=queryOrderDetail&orderId=${sessionScope.orderId}">查看详情</a></td>
</tr>
</c:forEach>
</table>
上面页面中的,用户签收订单