之前学习了使用J2EE开发一个模仿天猫商城整站的项目,期间学习到了不少知识。但是隔了一段时间再回看代码,居然有点生疏了~所以写下这篇博客,方便日后回顾,温故而知新,也可以和大家交流学习。

本篇介绍项目的后台管理开发,模块主要分为:分类管理,用户管理,订单管理,分类下的产品管理,分类属性管理,产品属性管理和产品图片管理等等。。。

浏览地址:http://how2j.cn/tmall/admin_category_list

下载地址:链接:https://pan.baidu.com/s/12EnpGy8gr-TC6KL_JRSiCg 密码:lrxu

涉及到的知识

前端:html+css+JavaScript+jQuery+Bootstrap

后端:j2ee

数据库:mysql

数据库表关系图

模块开发

这里使用的是MVC开发模式,jsp作为显示的层面,servlet充当控制层,bean和dao作为模型

如果一个功能对应一个servlet,那么一个项目里面就有很多很多的servlet,web.xml也要配置很多次。这里的解决方案是使用Filter结合servlet。假设访问路径是 http://127.0.0.1:8080/tmall/admin_category_list,首先设置一个过滤器BackServletFilter,对所有请求进行拦截,判断访问的地址是否以/admin_开头,如果是,那么做如下操作

1.取出两个下划线之间的值 category

2.取出最后一个下划线之后的值 list

3. 然后根据这个值,服务端跳转到categoryServlet,并且把list这个值传递过去

package tmall.filter;import java.io.IOException;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.lang.StringUtils;public class BackServletFilter implements Filter {public void destroy() {}@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) res;String contextPath=request.getServletContext().getContextPath();String uri = request.getRequestURI();uri =StringUtils.remove(uri, contextPath);if(uri.startsWith("/admin_")){     String servletPath = StringUtils.substringBetween(uri,"_", "_") + "Servlet";String method = StringUtils.substringAfterLast(uri,"_" );request.setAttribute("method", method);req.getRequestDispatcher("/" + servletPath).forward(request, response);return;}chain.doFilter(request, response);}public void init(FilterConfig arg0) throws ServletException {}
}

紧接着,定义一个BaseBackServlet进行抽取,原理是利用反射技术。让categoryServlet 继承BaseBackServlet,重写BaseBackServlet中的service函数。在调用categoryServlet中的dopost或者doget方法前,BaseBackServlet会被调用,根据filter传递过来method的值,借助反射,调用categoryServlet中对用的方法,最后根据servlet中返回的字段,选择进行服务器端的跳转或者是客户端的跳转。

package tmall.servlet;import java.io.InputStream;import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.List;
import java.util.Map;import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;import tmall.dao.CategoryDAO;
import tmall.dao.OrderDAO;
import tmall.dao.OrderItemDAO;
import tmall.dao.ProductDAO;
import tmall.dao.ProductImageDAO;
import tmall.dao.PropertyDAO;
import tmall.dao.PropertyValueDAO;
import tmall.dao.ReviewDAO;
import tmall.dao.UserDAO;
import tmall.util.Page;public abstract class BaseBackServlet extends HttpServlet {public abstract String add(HttpServletRequest request, HttpServletResponse response, Page page) ;public abstract String delete(HttpServletRequest request, HttpServletResponse response, Page page) ;public abstract String edit(HttpServletRequest request, HttpServletResponse response, Page page) ;public abstract String update(HttpServletRequest request, HttpServletResponse response, Page page) ;public abstract String list(HttpServletRequest request, HttpServletResponse response, Page page) ;protected CategoryDAO categoryDAO = new CategoryDAO();protected OrderDAO orderDAO = new OrderDAO();protected OrderItemDAO orderItemDAO = new OrderItemDAO();protected ProductDAO productDAO = new ProductDAO();protected ProductImageDAO productImageDAO = new ProductImageDAO();protected PropertyDAO propertyDAO = new PropertyDAO();protected PropertyValueDAO propertyValueDAO = new PropertyValueDAO();protected ReviewDAO reviewDAO = new ReviewDAO();protected UserDAO userDAO = new UserDAO();public void service(HttpServletRequest request, HttpServletResponse response) {try {/*获取分页信息*/int start= 0;int count = 5;try {start = Integer.parseInt(request.getParameter("page.start"));} catch (Exception e) {}try {count = Integer.parseInt(request.getParameter("page.count"));} catch (Exception e) {}Page page = new Page(start,count);/*借助反射,调用对应的方法*/String method = (String) request.getAttribute("method");Method m = this.getClass().getMethod(method, javax.servlet.http.HttpServletRequest.class,javax.servlet.http.HttpServletResponse.class,Page.class);String redirect = m.invoke(this,request, response,page).toString();/*根据方法的返回值,进行相应的客户端跳转,服务端跳转,或者仅仅是输出字符串*/if(redirect.startsWith("@"))response.sendRedirect(redirect.substring(1));else if(redirect.startsWith("%"))response.getWriter().print(redirect.substring(1));elserequest.getRequestDispatcher(redirect).forward(request, response);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();throw new RuntimeException(e);}}

1.分类管理

分类管理是后台开发的起始,是产品管理的父级,这里实现了分类管理增删查改的基本操作,同时提供分页查询,分类属性的增删查改,分类下产品管理入口(在跳转时传递分类id查找分类下的产品)。下面是分类下分页查询代码,分页查询在其他功能开发中都会用到,在page中设置start和count作为参数传入categoryDao中,查询出条件下的分类集合,用request传到jsp页面中去

public String list(HttpServletRequest request, HttpServletResponse response, Page page) {List<Category> cs = categoryDAO.list(page.getStart(),page.getCount());int total = categoryDAO.getTotal();page.setTotal(total);request.setAttribute("thecs", cs);request.setAttribute("page", page);return "admin/listCategory.jsp";}

2.分类属性管理

每个分类都有对应属性,例如电视机,会有产地,尺寸,颜色等属性,所以我们得对它的这些属性进行管理。例如做一个增加操作,提交数据是在istProperty.jsp页面中的,除了提交属性名称,还会提交cid,在PropertyServlet中根据获取到的cid,name参数,创建新的Property对象,并插入到数据库,客户端跳转到admin_property_list,并带上参数cid。

listProperty.jsp代码片段

<form method="post" id="addForm" action="admin_property_add"><table class="addTable"><tr><td>属性名称</td><td><input id="name" name="name" type="text"class="form-control"></td></tr><tr class="submitTR"><td colspan="2" align="center"><input type="hidden" name="cid" value="${c.id}"><button type="submit" class="btn btn-success">提 交</button></td></tr></table></form>

propertyServlet代码片段

public String add(HttpServletRequest request, HttpServletResponse response, Page page) {int cid = Integer.parseInt(request.getParameter("cid"));Category c = categoryDAO.get(cid);String name= request.getParameter("name");Property p = new Property();p.setCategory(c);p.setName(name);propertyDAO.add(p);return "@admin_property_list?cid="+cid;
}

3.产品管理

产品管理这里也是关于增删查改的基本操作,有不同的是page下必须多夹带一个参数,这个参数就是产品父级-分类的id,在产品的分页查询需要用到这个参数,查询访问的是ProductServlet的list()方法,首先获取分类 cid,基于cid,获取当前分类下的产品集合, 获取当前分类下的产品总数,并且设置给分页page对象,拼接字符串"&cid="+c.getId(),设置给page对象的Param值。 因为产品分页都是基于当前分类下的分页,所以分页的时候需要传递这个cid,封装好数据,服务端跳转到admin/listProduct.jsp页面, 在listProduct.jsp页面上使用c:forEach 遍历ps集合,并显示

public String list(HttpServletRequest request, HttpServletResponse response, Page page) {int cid = Integer.parseInt(request.getParameter("cid"));Category c = categoryDAO.get(cid);List<Product> ps = productDAO.list(cid, page.getStart(),page.getCount());int total = productDAO.getTotal(cid);page.setTotal(total);page.setParam("&cid="+c.getId());request.setAttribute("ps", ps);request.setAttribute("c", c);request.setAttribute("page", page);return "admin/listProduct.jsp";
}

listProduct.jsp代码片段

<c:forEach items="${ps}" var="p"><tr><td>${p.id}</td><td><c:if test="${!empty p.firstProductImage}"><img width="40px" src="img/productSingle/${p.firstProductImage.id}.jpg"></c:if></td><td>${p.name}</td><td>${p.subTitle}</td><td>${p.orignalPrice}</td><td>${p.promotePrice}</td><td>${p.stock}</td><td><a href="admin_productImage_list?pid=${p.id}"><spanclass="glyphicon glyphicon-picture"></span></a></td><td><a href="admin_product_editPropertyValue?id=${p.id}"><spanclass="glyphicon glyphicon-th-list"></span></a></td><td><a href="admin_product_edit?id=${p.id}"><spanclass="glyphicon glyphicon-edit"></span></a></td><td><a deleteLink="true"href="admin_product_delete?id=${p.id}"><spanclass="     glyphicon glyphicon-trash"></span></a></td></tr>
</c:forEach>

4.产品图片管理

每个产品的图片有分为单张图片和详细信息图片,单张图片是为了展示产品外观,而详细信息图片是为了展示产品详细信息。parseUpload 获取上传文件的输入流,parseUpload 方法会修改params 参数,并且把浏览器提交的type,pid信息放在其中,从params 中取出type,pid信息,并根据这个type,pid,借助productImageDAO,向数据库中插入数据,根据request.getSession().getServletContext().getRealPath( "img/productSingle"),定位到存放分类图片的目录,除了productSingle,还有productSingle_middle和productSingle_small。 因为每上传一张图片,都会有对应的正常,中等和小的三种大小图片,并且放在3个不同的目录下,文件命名以保存到数据库的分类对象的id+".jpg"的格式命名,根据步骤1获取的输入流,把浏览器提交的文件,复制到目标文件,再借助ImageUtil.resizeImage把正常大小的图片,改变大小之后,分别复制到productSingle_middle和productSingle_small目录下, 处理完毕之后,客户端条跳转到admin_productImage_list?pid=,并带上pid。

productImageServlet代码片段

public String add(HttpServletRequest request, HttpServletResponse response, Page page) {//上传文件的输入流InputStream is = null;//提交上传文件时的其他参数Map<String,String> params = new HashMap<>();//解析上传is = parseUpload(request, params);     //根据上传的参数生成productImage对象String type= params.get("type");int pid = Integer.parseInt(params.get("pid"));Product p =productDAO.get(pid);ProductImage pi = new ProductImage();      pi.setType(type);pi.setProduct(p);productImageDAO.add(pi);//生成文件String fileName = pi.getId()+ ".jpg";String imageFolder;String imageFolder_small=null;String imageFolder_middle=null;if(ProductImageDAO.type_single.equals(pi.getType())){imageFolder= request.getSession().getServletContext().getRealPath("img/productSingle");imageFolder_small= request.getSession().getServletContext().getRealPath("img/productSingle_small");imageFolder_middle= request.getSession().getServletContext().getRealPath("img/productSingle_middle");}elseimageFolder= request.getSession().getServletContext().getRealPath("img/productDetail");File f = new File(imageFolder, fileName);f.getParentFile().mkdirs();// 复制文件try {if(null!=is && 0!=is.available()){try(FileOutputStream fos = new FileOutputStream(f)){byte b[] = new byte[1024 * 1024];int length = 0;while (-1 != (length = is.read(b))) {fos.write(b, 0, length);}fos.flush();//通过如下代码,把文件保存为jpg格式BufferedImage img = ImageUtil.change2jpg(f);ImageIO.write(img, "jpg", f);      if(ProductImageDAO.type_single.equals(pi.getType())){File f_small = new File(imageFolder_small, fileName);File f_middle = new File(imageFolder_middle, fileName);ImageUtil.resizeImage(f, 56, 56, f_small);ImageUtil.resizeImage(f, 217, 190, f_middle);}}catch(Exception e){e.printStackTrace();}}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return "@admin_productImage_list?pid="+p.getId();}

5.产品属性管理

每个产品都有各自的属性,比如电视机的颜色是红色。所以对产品属性的管理也无非是增删查改,这里用修改举例,修改时候使用了post提交ajax异步处理。使用监听输入框上的keyup事件,获取输入框里的,还有定义的pvid,借助JQuery的ajax函数 $.post,把id和值,提交到admin_product_updatePropertyValue,admin_product_updatePropertyValue导致ProductServlet的updatePropertyValue方法被调用, BaseBackServlet根据返回值"%success",直接输出字符串"success" 到浏览器, 浏览器判断如果返回值是"success",那么就把边框设置为绿色,表示修改成功,否则设置为红色,表示修改失败。

editProperty.jsp代码片段

$("input.pvValue").keyup(function(){var value = $(this).val();var page = "admin_product_updatePropertyValue";var pvid = $(this).attr("pvid");var parentSpan = $(this).parent("span");parentSpan.css("border","1px solid yellow");$.post(page,{"value":value,"pvid":pvid},function(result){if("success"==result)parentSpan.css("border","1px solid green");elseparentSpan.css("border","1px solid red");});
});

6.用户管理

这里就只是从数据库取出来,分页显示~

7.订单管理

后台订单管理只提供发货和查询的方法,下单和取消订单是由前台用户自己进行的。当订单状态是waitDelivery的时候,就会出现发货按钮,发货按钮链接跳转到admin_order_delivery,OrderServlet.delivery()方法被调用,获取对象id,修改发货时间,设置发货状态,更新数据库,跳转,完成了

orderServlet片段

public String delivery(HttpServletRequest request, HttpServletResponse response, Page page) {int id = Integer.parseInt(request.getParameter("id"));Order o = orderDAO.get(id);o.setDeliveryDate(new Date());o.setStatus(OrderDAO.waitConfirm);orderDAO.update(o);return "@admin_order_list";
}

总结下来,j2ee开发增删查改第一步先是获取到传递过来的数据,在根据实际业务对数据进行操作,到这里后台部分就写完了

【J2EE】模仿天猫商城(后台篇)相关推荐

  1. 模仿天猫商城的J2EE商城网站项目后端——servlet+filter配合详细分析

    目录 模仿天猫商城的J2EE商城网站项目后端2--需求分析 代码工作流程图(也是整个项目的代码工作流程图) 举例分析 1 后台servlet过滤器BackServletFilter对其进行拦截,并进行 ...

  2. 模仿天猫商城的J2EE商城网站项目后端5——bean包

    目录 User.java Product.java Category.java ProductImage.java Property.java PropertyValue.java OrderItem ...

  3. 模仿天猫商城数据库分析

    仿天猫商城数据库分析 数据结构图 页面分析 前端 注册页面 - 页面图片 - 功能描述 登陆页面 - 功能描述 账号登陆 - 页面执行的SQL语句 校验账户密码是否匹配,匹配则为1,否则为0 SELE ...

  4. 仿天猫商城后台数据库设计及运用

    仿天猫商城数据库关系 仿天猫商城系统页面 后台数据页面.功能和SQL语句 1. 功能:向数据库category表中插一条数据,后台记录商品类 INSERT INTO category(name)VAL ...

  5. java项目源码-模仿天猫商城网站

    已经部署好了,体验地址 模仿天猫网站 购物车: 确认收货 可以免费学到分页管理 地址

  6. java实战项目源码-模仿天猫商城网站

    已经部署好了,体验地址,可以注册个账号买东西试试,注意不要输入真实的账号密码 模仿天猫网站 可以免费学到分页管理 购物车: 确认收货 地址

  7. 天猫商城项目演化(一)

    ** 模仿天猫电商网站1.0&2.0&3.0 项目名称:仿天猫商城1.0 ** 目录: 1.引言 软件背景 2.项目概述 2.1软件基本需求介绍 2.1.1前台展示 2.1.2用户交互 ...

  8. SSM项目-模仿天猫网站

    模仿天猫商城网站地址(已经部署在阿里云了) 1. SSM是Spring, SpringMVC, Mybatis 2. SSM实战教程 SSM详细介绍 首先准备数据库 how2java 如果没有安装数据 ...

  9. 仿天猫 java web_JAVA WEB项目教程-模仿天猫J2EE版

    做一个模仿个天猫官网的J2EE项目,来练手吧 1. 项目演示地址 2. 学习思路 其实呢,要在网上找一个J2EE项目是很容易的,随便在百度或者git搜索,都是一大把. 但是拿到这样的搜索来的J2EE项 ...

最新文章

  1. 接口幂等性的设计之————redis分布式锁的应用
  2. 服务器应用程序不可用您试图在此 Web 服务器上访问的 Web 应用程序当前不可用。请点击 Web 浏览器中的“刷...
  3. 王力宏《十八般武艺》新碟 测评
  4. postfix 部署ssl后还是25_宝塔面板的邮局管理器Postfix无法启动解决办法
  5. (vue基础试炼_03)使用vue.js实现TodoList
  6. (软件工程复习核心重点)第四章总体设计习题
  7. Apache和Nginx防盗链
  8. 命令窗口ping oracle,Oracle中tnsping命令解析
  9. XCODE GDB这个是老版本xcode,新版的是lldb
  10. 35、IFE任务34——听指令的小方块(二)
  11. C# 数组拷贝 byte数组拷贝,char数组拷贝
  12. 虚拟机系统iso镜像下载_微软Windows 10 Build 19013(20H1)简体中文版ISO镜像可供下载...
  13. python实验心得_Python实训周总结
  14. Ubuntu 18.04配置静态IP地址
  15. 十六进制编辑器HxD Hex Editor x64 v2.3.0.0
  16. Java三部曲(二)JavaWeb
  17. “大学教育的目的”-- 芝加哥大学Andrew Abbott教授的演讲
  18. LSF_安装(UNIX or Linux)
  19. css的`class`选择器选择前缀.
  20. javauniapp+SpringBoot即时通讯聊天软件源码

热门文章

  1. Hangfire详解
  2. 干货 | 手把手教你iOS自定义视频压缩
  3. 电脑录屏软件帧率设置详解
  4. 大数据下的用户画像标签去重
  5. 「CH2401」送礼物 解题报告
  6. Q1成绩:华为可穿戴设备增幅亮眼,Uber亏损10亿美元!
  7. 计算机学院条幅内容,学院迎新活动标语横幅
  8. 华为鸿蒙2.0来了,挑战谷歌安卓APP成关键?
  9. LC-3 子程序调用与模拟栈调用递归函数
  10. 《Turtle绘图》Python用Turtle库绘制多啦爱梦、小猪佩奇、皮卡丘等卡通人物