图书商城后台功能实现

发布时间 2023-05-26 10:42:44作者: 2小只

后台功能实现

1 后台管理介绍

1.1 后台页面

后台页面都在adminjsps目录下:

 

1.2 后台功能模块介绍

后台功能模块分为:

l 管理员模块:

  • 管理员登录;
  • 管理员退出;

l 分类管理模块:

  • 查看所有分类;
  • 添加一级分类;
  • 添加二级分类;
  • 编辑一级分类;
  • 编辑二级分类;
  • 删除一级分类;
  • 删除二级分类;

l 图书管理模块:

  • 查看指定分类图书;
  • 查看指定条件图书;
  • 添加新图书;
  • 编辑图书;
  • 删除图书;

l 订单管理模块:

  • 查看所有订单;
  • 查看指定状态订单;
  • 查看订单详细信息;
  • 取消订单;
  • 订单发货。

其中只有管理员模块是前台没有的,其他三个模块前台都有。但是,尽管前台有这三个模块,前后台也不能共享Servlet!但前后台可以共享ServiceDAO层!所以只有管理员模块需要创建所有层的类,而其他三个模块只需要创建Servlet层类即可。

  后台有很多功能与前台是相同的,例如按分类查看图书功能,只是转发的页面是后台页面而已,所以这里很多功能就不在赘述了。

2 后台管理员模块

后台管理员模块功能:

l 管理员登录;

l 管理员退出。

2.1 后台管理员相关类创建

Admin类对应t_admin表,不再废话,直接给出基本代码;

Admin.java

public class Admin {

private String adminId;//ID

private String adminname;//管理员名

private String adminpwd;//管理员密码

}

 

2.2 管理员登录

login.jsp是后台登录页面,页面本身提供了表单显示功能。提交表单请求AdminServlet#login()方法:

把表单数据封装到Admin对象中;

使用表单数据调用AdminService#login()方法查询用户;

  • 如果查询到用户说明登录成功:把查询到的用户保存到session中,转发到index.jsp
  • 如果没有查询到,说明登录失败:在request中保存错误信息,转发到login.jsp

  登录成功后转发到/adminjsps/admin/index.jsp页面,该页面top.jsp部分需要显示当前用户名,所以需要修改该页面。

2.3 管理员退出

  top.jsp页面中存在“退出”链接,让该链接请求AdminServlet#quit()方法。quit()方法从session中移除当前用户,转发到login.jsp页面。

3 分类管理

分类管理功能:

l 查看所有分类;

l 添加一级分类;

l 添加二级分类;

l 编辑一级分类;

l 编辑二级分类;

l 删除一级分类;

l 删除二级分类;

3.1 分类管理相关类创建

ServiceDao与前台共享即可,无需再创建,而Servlet需要单独创建。

l cn.itcast.bookstore.admin.category.web.servlet.AdminCategoryServlet

web.xml中配置该类时,<url-partern>/admin/AdminCategoryServlet,方法后面添加登录过滤器。不只是该模块的Servlet如此,图书和订单模块都是如此。

3.2 查看所有分类

 

top.jsp页面点击“分类管理”链接完成查看所有分类。该链接请求AdminCategoryServlet#findAll()方法,得到所有分类,即List<Category>,然后保存到request中,转发到/adminjsps/admin/category/list.jsp页面显示。

CategoryServiceCategoryDao都已经写好了,所以无需再写!

3.3 添加一级分类

/adminjsps/admin/category/list.jsp中点击添加一级分类到达/adminjsps/admin/category/add.jsp页面。

add.jsp页面提交表单,请求AdminCategoryServlet#addOneLevel()方法,完成添加分类。addOneLevel()在添加完成后,调用AdminCategoryServlet#findAll()方法,回到list.jsp显示所有分类。

3.4 添加二级分类

添加二级分类共两步:一是到达表单页面,二是提交表单完成添加。

  1. 到达表单页面

  在/adminjsps/admin/category/list.jsp中,在某个一级分类上点击“添加二级分类”,请求AdminCategoryServlet#addTwoLevelPre()方法,传递一级分类cidaddTwoLevelPre()会获取所有一级分类,以及当前一级分类cid,然后转发到/adminjsps/admin/category/add2.jsp页面。

 

add2.jsp页面中显示所有一级分类,因为二级分类有父分类。

 

  1. 完成添加二级分类

add2.jsp页面提交表单,完成添加二级分类。提交表单请求AdminCategoryServletaddTwoLevel()方法:

封装表单数据到Category child对象中;

child指定cid

获取表单pid,创建Category parent,把pid设置给parentcid

parent设置给child

调用categoryService#add(Category)方法完成添加;

调用AdminCategoryServlet#findAll(),回到list.jsp

3.5 修改一级分类

修改一级分类分为两步:

list.jsp中点击某个一级分类上的“修改”,到达edit.jsp

在 edit.jsp页面提交表单。

  1. 到达edit.jsp

/adminjsps/admin/category/list.jsp页面上,点击某个一级分类上的“修改”链接,请求AdminCategoryServlete#editOneLevelPre()方法,传递cid

editOneLevelPre()方法通过cid加载当前分类,保存到request中,转发到edit.jsp,在表单中显示。

 

  1. 提交表单完成修改一级分类

edit.jsp页面提交表单,请求AdminCategoryServlet#editOneLevel()方法,传递表单数据,其中表单中需要添加隐藏字段cid,即被修改的分类id

editOneLevel()调用service完成修改后,返回到list.jsp

3.6 修改二级分类

修改二级分类也是分为两步:

list.jsp中点击某个二级分类上的“修改”,到达edit2.jsp

edit2.jsp页面提交表单。

  1. 到达edit2.jsp

/adminjsps/admin/category/list.jsp页面上,点击某个二级分类上的“修改”链接,请求AdminCategoryServlet#editTwoLevelPre()方法,传递cid

editTwoLevelPre()方法通过cid加载当前分类,保存到request中,再加载所有一级分类保存到request中。转发到/adminjsps/admin/category/edit2.jsp页面。

edit2.jsp在表单中显示当前二级Category对象,而且还要把所有一级分类显示到下拉列表中。然后让下拉列表上显示当前Category的父分类。

 

  1. edit2.jsp提交表单,完成修改

/adminjsps/admin/edit2.jsp页面上提交表单,请求AdminCategoryServlet#editTwoLevel()方法,传递表单数据,还有添加隐藏字段cid,即要修改的分类cid

editTowLevel()方法获取表单数据,封装到Category child对象中,再获取pid,创建Category parent,把pid设置给parent,再把parent设置给child,然后调用categoryServiceedit(Category)方法完成修改。最后回到list.jsp显示。

3.7 删除一级分类

/adminjsps/admin/category/list.jsp页面上,点击某个一级分类上的“删除”链接完成删除。点击链接请求AdminCategoryServlet#deleteOneLevel()方法,传递当前一级分类的cid

deleteOneLevel()方法首先获取cid,然后调用CategoryServicedeleteOneLevel()方法完成删除,转发到list.jsp显示。注意,CategoryService#deleteOneLevel()方法可能会抛出CategoryService异常,如果抛出了异常,那么Servlet会把异常信息保存到request中,转发到/adminjsps/msg.jsp页面显示。

CategoryService#deleteOneLevel()方法会先判断该1 级分类下是否存在子分类,如果存在那么它会抛出CategoryService异常;如果不存在,那么删除该分类。

3.8 删除二级分类

/adminjsps/admin/category/list.jsp页面上,点击某个二级分类上的“删除”链接完成删除。点击链接会请求ActionCategoryServlet#deleteTwoLevel()方法,传递当前二级分类的cid

deleteTwoLevel()方法首先获取cid,然后调用CategoryServicedeleteTwoLevel()方法完成删除,转发到list.jsp显示。注意,CategoryService#deleteTwoLevel()方法可能会抛出CategoryException异常,如果抛出了异常,那么Servlet会把异常信息保存到request中,转发到/adminjsps/msg.jsp页面显示。

CategoryService#deleteTowLevel()方法会先判断该2级分类下是否存在图书,如果存在那么抛出CategoryException异常;如果不存在,那么删除该分类。

4 图书管理

top.jsp上点击“图书管理”进入图书管理主页:/adminjsps/admin/book/main.jspmain.jsp是框架页,分为左部和中部,其中左部为所有分类(与前台主页左部相同),中部默认显示body.jspbody.jsp有两个链接:添加图书和高级搜索。

 

图书管理功能如下:

l 按分类查询图书;

l 按作者查询图书;

l 按出版社查询图书;

l 高级搜索(多条件组合查询);

l 查询图书详细;

l 添加图书;

l 编辑图书;

l 删除图书。

后台图书管理中有很多功能与前台一样,可参照前台完成。

4.1 与前台相同功能实现

1. 左部显示所有分类

修改main.jspleft框架,让其请求AdminCategoryServletfindAllForBook()方法;

AdminCategoryServlet类添加findAllForBook()方法,让其获取所有分类,然后转发到/adminjsps/admin/book/left.jsp页面;

/adminjsps/admin/book/left.jsp页面中使用Javascript小工具(Q6Menu)显示所有分类。

 

2. 按分类查询图书(分页显示)

点击Q6Menu上的2级分类,请求AdminBookServlet#findByCategory()方法;

该方法实现参照BookServlet#findByCategory()方法,但最终转发到/adminjsps/admin/book/list.jsp页面;

修改list.jsp,显示图书列表。

 

  1. 按作者、出版社查询

修改list.jsp上的链接,让其请求AdminBookServlet对应的方法;

参数BookServlet对应方法完成,最后转发到/adminjsps/admin/book/list.jsp页面;

 

  1. 高级搜索

修改gj.jsp上的表单,让其请求AdminBookServletfindByCombination()方法;

该方法参照BookServlet实现,最后转发到/adminjsps/admin/book/list.jsp页面;

4.2 加载图书

list.jsp上点击图书的图片、图书名,请求AdminBookServlet#load()方法,load()方法完成加载图书,转发到desc.jsp显示。

desc.jsp页面不仅可以显示图书详细信息,而且还可以作为编辑图书的表单。该页面上有一个“编辑或删除”复选框,如果勾选了它,那么desc.jsp页面上就显示表单,用来作为编辑图书而用;如果没有勾选desc.jsp只是显示图书详细信息。

 

因为desc.jsp不仅用来显示图书详细,而且还用来作为编辑图书的表单页面,默认desc.jsp页面使用非表单形式显示图书。

desc.jsp要显示表单时,还要允许用户修改图书的分类,所以load()方法还要传递所有1 级分类,以及当前图书所有1 级分类下的所有2 级分类。并且,用户在修改了1 级分类后,页面还要向服务器发出异步请求,请求当前1 级分类下的所有2级分类,然后显示在下拉列表中。

desc.jsp页面:

两种显示book方式:一是非表单显示,二是表单显示;

l javascript

  • “编辑或删除”复选框添加事件,未勾选时使用非表单显示;勾选时使用表单显示;
  • 1级分类下拉列表添加onchange事件,异步请求当前1级分类下所有2级分类,然后显示在2 级分类下拉列表中。
  • 因为desc.jsp页面的表单有两个提交按钮(编辑和删除),所以需要为这两个提交按钮添加事件,为表单添加隐藏字段method的值,然后提交表单。

AdminBookServlet#load()方法:

获取bid加载图书,保存到request中;

获取所有1级分类,保存到request中;

获取当前book所属1级分类下的所有2级分类,保存到request中;

转发到desc.jsp

load()

public String load(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

/*

 * 1. 获取bid,通过bid加载book,保存到request

 */

String bid = request.getParameter("bid");

Book book = bookService.load(bid);

request.setAttribute("book", book);

/*

 * 2. 获取所有1级分类,保存到request

 */

request.setAttribute("parents", categoryService.findParents());

/*

 * 3. 获取当前图书所属1级分类下的所有2级分类

 */

// 获取当前图书所属1级分类cid

String pid = book.getCategory().getParent().getCid();

request.setAttribute("children", categoryService.findChildren(pid));

return "/adminjsps/admin/book/desc.jsp";

}

 

desc.jsp需要显示1级、2级分类的下拉列表。

<c:forEach items="${parents }" var="parent">

<option value="${parent.cid }" <c:if test="${book.category.parent.cid eq parent.cid }">selected="selected"</c:if>>${parent.cname }</option>

</c:forEach>

<c:forEach items="${children }" var="child">

<option value="${child.cid }" <c:if test="${book.category.cid eq child.cid }">selected="selected"</c:if>>${child.cname }</option>

</c:forEach>

 

  desc.jsp需要添加异步请求,在1级分类修改后,请求新的1级分类下所有2级分类,并显示在2级分类的下拉列表中。

/*

1级分类下拉列表添加改变事件

在重新选择了1级分类后,加载该1级分类的所有2级分类并显示在2级分类下拉列表中

*/

$("#pid").change(function() {

var pid = $(this).val();//获取新的1级分类id

$("#cid").empty();//清空2级分类下拉列表

// 添加头选项

$("#cid").append($("<option value=''>==请选择2级分类==</option>"));

if(pid) {//如果新的1级分类不为空!

$.ajax({

url:"<c:url value='/admin/AdminCategoryServlet'/>",

data:{method:"childrenForAjax", pid:pid},

dataType:"json",

type:"POST",

async:"false",

cache:"false",

success:function(children) {

// 循环遍历所有2级分类

for(var i = 0; i < children.length; i++) {

// 创建选项同

var option = $("<option>").attr("value", children[i].cid).text(children[i].cname);

// 2级分类下拉列表中添加选项同

$("#cid").append(option);

}

}

});

}

4.3 编辑图书

desc.jsp页面点击“编辑图书”按钮完成编辑图书,该链接请求AdminBookServletedit()方法。

edit()方法封装表单数据,调用BookService#edit(Book)方法完成编辑图书。然后保存“编辑成功”到request中,转发到/adminjsps/msg.jsp显示。

注意,编辑图书功能不支付编辑图书图片,所以在BookDao中的update语句不能修改image_bimage_w两列。

 

4.4 删除图书

desc.jsp页面点击“删除图书”按钮完成删除图书,该链接请求AdminBookServletdelete()方法。

delete()调用BookService#delete(bid)方法,完成删除图书。然后保存“删除成功”到request中,转发到/adminjsps/msg.jsp显示。

4.5 添加图书

添加图书分为两步:

点击body.jsp上的“添加图书”链接,到达add.jsp

add.jsp提交表单。

  1. 点击“添加图书”链接,到达add.jsp

点击“添加图书”链接,请求AdminBookServlet#addPre()方法,addPre()获取所有1级分类,然后转发到add.jsp页面。

add.jsp显示所有1级分类到下拉列表中,当用户显示1级后,需要发送异步请求,获取该1级分类下所有2级分类,然后显示到2级分类下拉列表中。(与编辑图书一样)

  1. add.jsp提交表单,完成添加图书。

添加图书需要上传图片,这一功能不能放到AdminBookServlet,而应该为其单独提供一个ServletAdminAddBookServlet

AdminAddBookServlet中需要使用commons-fileupload组件解析表单。获取所有表单项,封装到Book对象中,然后调用BookService#add(Book)方法完成添加,最终转发到msg.jsp显示成功信息。

注意,要对上传的图片扩展名进行校验!然后保存图片到book_img目录下!

5 订单管理

top.jsp上点击“订单管理”查看所有订单。

 

  订单管理功能如下:

l 查看所有订单;

l 查看未付款订单;

l 查看未发货订单;

l 查看未确认收货订单;

l 查看交易成功订单;

l 查看已取消订单;

l 查看订单详细信息;

l 取消未付款订单;

l 订单发货。

后台订单功能与前台都是相同的,可参照前台完成。

5.1 与前台相同功能实现

1. 查看所有订单(分页显示)

这个功能前台没有,但与前台的“我的订单”很相似。

修改top.jsp中“订单管理”链接,请求AdminOrderServlet#findAll()方法;

l AdminOrderServlet#findAll()àfindAll()OrderService#findAll()àOrderDao#findAll()方法都参照前台的“我的订单来完成”来完成。最后转发到/adminjsps/admin/order/list.jsp页面。

修改list.jsp页面,不同状态显示不同链接。

 

2. 按状态查询订单(分页显示)

这个功能前台没有,但与前台的“我的订单”很相似。

修改/adminjsps/admin/order/list.jsp5个按状态查询的链接,请求AdminOrderServleet#findByStatus()方法,参数订单状态。最后转发到/adminjsps/admin/order/list.jsp页面。

  1. 查看订单详细信息

list.jsp页面点击订单编号链接,或点击查看链接,请求AdminOrderServlet#load()方法,传递订单oid,以及oper=desc

l load()方法加载订单,保存到request中,把oper也保存到request中,转发到desc.jsp页面。

l desc.jsp页面显示订单信息,并根据oper显示按钮。

5.2 取消订单和订单发货

取消订单和订单发货都是修改订单状态的功能!

修改desc.jsp页面中“取消订单”和“发货”两个链接,请求AdminOrderServletcancel()deliver()方法;

调用orderService.updateStatus(String oid, int status)方法完成对订单状态的修改;

保存成功信息到request中,转发到msg.jsp页面显示!

 

6 登录过滤器

添加后台管理员登录过滤器!

页面:/adminjsps/admin/*

l Servlet/admin/*