二、商品管理的准备工作

商品表:

  1. CREATE TABLE `product` (
  2. `pid` INT(10) PRIMARY KEY AUTO_INCREMENT,#主键自增
  3. `pname` VARCHAR(50) NOT NULL,#商品名字
  4. `color` VARCHAR(50),#颜色
  5. `price` DOUBLE NOT NULL,#价格
  6. `description` VARCHAR(500),#描述
  7. `pic` VARCHAR(200),#商品图片
  8. `state` INT(5) DEFAULT '0', # 0:正常 1:热门 2:为你推荐 3:新品 4:小米明星单品
  9. `version` VARCHAR(50),#型号
  10. `product_date` DATETIME,#生产日期
  11. cid INT(10) # 所属的分类
  12. ) ;

包结构搭建:

pojo、dao、service、servlet(配置web.xml!!!!!!!!!!!!!!!!!!!!)

三、商品分页查询

后台代码略:

显示分类名称功能:

分析图:

image.png

代码实现:

service中:

  1. private CategoryDao cd = new CategoryDao();
  2. public PageBean<Product> selectPlist(PageBean<Product> pb) {
  3. List<Product> plist = pd.selectPlist(pb);
  4. //遍历plist获取cid的值
  5. for(Product pro:plist) {
  6. //获取cid的值
  7. int cid = pro.getCid();
  8. //根据cid查询Category对象
  9. Category category = cd.selectByCid(cid+"");
  10. //将category对象封装到Product里
  11. pro.setCategory(category);
  12. }
  13. pb.setResult(plist);
  14. //查询总记录数
  15. int totalCount = pd.selecCount();
  16. pb.setTotalCount(totalCount);
  17. return pb;
  18. }

product_list.jsp:

显示分类名称:

${p.category.cname}

四、添加商品

4.1 跳转到添加商品页面

问题:直接跳还是要走服务器?

标准:看跳转过去的页面要不要回显数据?

需求:走服务器查出所有的分类信息回显到下拉列表中?

代码实现:

product_list.jsp:

  1. <li onclick="toAdd()" style="cursor: pointer;" id="addProduct" ><span><img src="${pageContext.request.contextPath}/admin/images/t01.png" /></span>添加商品</li>
  2. <script type="text/javascript">
  3. //跳转到添加商品页面
  4. function toAdd(){
  5. location.href = "/dami/product?method=toAdd";
  6. }
  7. </script>

ProductServlet:

  1. //跳转到添加商品页面
  2. protected void toAdd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. //1、获取数据
  4. //2、调用业务
  5. CategoryService cs = new CategoryService();
  6. //查询所有分类信息
  7. List<Category> clist = cs.findAll();
  8. //3、结果的展示
  9. request.setAttribute("clist", clist);
  10. request.getRequestDispatcher("/admin/product_add.jsp").forward(request, response);
  11. }

CategoryService:

  1. public List<Category> findAll() {
  2. // TODO Auto-generated method stub
  3. return cd.findAll();
  4. }

CategoryDao:

  1. public List<Category> findAll() {
  2. String sql = "select * from category";
  3. try {
  4. return qr.query(sql, new BeanListHandler<Category>(Category.class));
  5. } catch (SQLException e) {
  6. // TODO Auto-generated catch block
  7. e.printStackTrace();
  8. return null;
  9. }
  10. }

product_add.jsp

  1. <!-- 商品分类信息 -->
  2. <li>
  3. <label>商品分类</label>
  4. <select name="cid" class="dfinput">
  5. <option value="0">===请选择===</option>
  6. <c:if test="${not empty clist}">
  7. <c:forEach items="${clist}" var="c">
  8. <option value="${c.cid}">${c.cname}</option>
  9. </c:forEach>
  10. </c:if>
  11. </select>
  12. </li>

4.2 添加商品

因为涉及到了图片的上传,注意浏览器、服务的操作步骤

代码略

五、删除单个商品

product_list.jsp

  1. <a href="javascript:void(0)" onclick="deleteByPid(${p.pid})">删除</a>
  2. //根据pid删除商品
  3. function deleteByPid(pid){
  4. if(confirm("是否确认要删除该商品呢???")){
  5. location.href = "/dami/product?method=deleteByPid&pid="+pid;
  6. }
  7. }

Servlet:

  1. //根据pid删除商品
  2. protected void deleteByPid(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. //1、获取数据
  4. String pid = request.getParameter("pid");
  5. //2、调用业务
  6. ProductService ps = new ProductService();
  7. ps.deleteByPid(pid);
  8. //3、结果的展示
  9. response.sendRedirect("/dami/product?method=selectPlist&pageNumber=1");
  10. }

Service:

  1. public void deleteByPid(String pid) {
  2. pd.deleteByPid(pid);
  3. }

Dao:

  1. public void deleteByPid(String pid) {
  2. String sql = "DELETE FROM product WHERE pid = ?";
  3. try {
  4. qr.update(sql, pid);
  5. } catch (SQLException e) {
  6. // TODO Auto-generated catch block
  7. e.printStackTrace();
  8. }
  9. }

六、首页的头部

  1. <a class="mix" href="/xiaomi/login.jsp">登录</a>

访问项目的路径:项目名目前是写死的状态 存在的问题:一旦项目名改变了,那么页面路径中所有的名字都要更改

解决:动态获取项目名

  • Servlet中

    1. String path = request.getContextPath();
  • Jsp

    1. ${pageContext.request.contextPath}

头部信息展示问题:

分析图:

image.png

代码实现:

login.jsp 改一处代码:

  1. else if(msg == "1"){
  2. //跳转到首页
  3. location.href= "${pageContext.request.contextPath}/index.jsp";
  4. }

UserServelt中:

  1. if((phoneNumber + code).equals(sessionCode)) {
  2. //验证码正确
  3. msg = "1";
  4. //登录成功
  5. request.getSession().setAttribute("qianUser", user);
  6. }

index.jsp的头部:

  1. <div class="right">
  2. <c:if test="${empty qianUser}">
  3. <a class="mix" href="${pageContext.request.contextPath}/login.jsp">登录</a>
  4. <a href="${pageContext.request.contextPath}/register.jsp">注册</a>
  5. </c:if>
  6. <c:if test="${not empty qianUser}">
  7. <span style="color:red">欢迎您:${qianUser.name}</span>
  8. </c:if>
  9. <a class="max" href="">消息通知</a>
  10. <a href="trolley.html"><img src="img/cart.jpg" alt=""></a>
  11. </div>

七、首页动态展示分类名称

目前的问题:

  1. 登录成功后直接跳转到了index.jsp ,导致在首页无法动态显示分类名称
  2. 所以,登录成功后需要先跳转到服务器查询分类的数据

代码实现:

login.jsp

  1. location.href= "${pageContext.request.contextPath}/product?method=toIndex";

ProductServet:

  1. //跳转到首页
  2. protected void toIndex(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. //1、获取数据(暂无)
  4. //2、调用业务
  5. //查询所有分类
  6. CategoryService cs = new CategoryService();
  7. List<Category> clist = cs.findAll();
  8. request.setAttribute("clist", clist);
  9. //3、结果的展示
  10. request.getRequestDispatcher("/index.jsp").forward(request, response);
  11. }

因为需要根据order_number的值进行排序显示,所以需要在原来的sql加上order by 进行排序

  1. public List<Category> findAll() {
  2. String sql = "select * from category order by order_number asc";
  3. try {
  4. return qr.query(sql, new BeanListHandler<Category>(Category.class));
  5. } catch (SQLException e) {
  6. // TODO Auto-generated catch block
  7. e.printStackTrace();
  8. return null;
  9. }
  10. }

问题:

  1. 目前是只有登录成功才会执行查询所有分类并动态展示在首页,直接访问index.jsp数据显示不出来

解决思路:

  1. 在用户访问index.jsp之前,就将数据查出来存到域对象中(服务器启动时)

使用的技术:监听器

  1. 监听器:监听到某种行为去做一些事情
  2. 某种行为:服务器启动
  3. 做事情:执行contextInitialized()

解决的代码:

  1. @WebListener
  2. public class MyListener implements ServletContextListener {
  3. public void contextDestroyed(ServletContextEvent arg0) {
  4. // TODO Auto-generated method stub
  5. }
  6. //服务器启动时执行该方法
  7. public void contextInitialized(ServletContextEvent arg0) {
  8. System.out.println("服务器启动啦");
  9. ServletContext context = arg0.getServletContext();
  10. //1、获取数据(暂无)
  11. //2、调用业务
  12. //查询所有分类
  13. CategoryService cs = new CategoryService();
  14. List<Category> clist = cs.findAll();
  15. context.setAttribute("clist", clist);
  16. }
  17. }

image.png

login.jsp

  1. location.href= "${pageContext.request.contextPath}/index.jsp";

八、首页动态展示前五条小米明星单品

分析:

  • 什么时候查
    和查询分类数据一样,都是在服务器启动时查
  • 执行的sql
    SELECT * FROM product WHERE state = 4 LIMIT 0,5;

代码实现:

在监听器的方法中加:

  1. //查询前五条小米明星单品
  2. ProductService ps = new ProductService();
  3. List<Product> plist = ps.findAllProduct();
  4. context.setAttribute("starList", plist);

Service:

  1. public List<Product> findAllProduct() {
  2. // TODO Auto-generated method stub
  3. return pd.findAllProduct();
  4. }

Dao:

  1. public List<Product> findAllProduct() {
  2. String sql = "SELECT * FROM product WHERE state = 4 LIMIT 0,5";
  3. try {
  4. return qr.query(sql, new BeanListHandler<Product>(Product.class));
  5. } catch (SQLException e) {
  6. // TODO Auto-generated catch block
  7. e.printStackTrace();
  8. return null;
  9. }
  10. }

index.jsp进行数据的展示:

  1. <c:if test="${not empty starList}">
  2. <c:forEach items="${starList}" var="star">
  3. <div style="background-color: #fff;width: 234px;height:320px;float: left;margin-left: 11px; ">
  4. <a href="${pageContext.request.contextPath}/product?method=toProductDetail&pid=${star.pid}" target="_blank">
  5. <img class="time_min" style="width:234px;height: 234px;" src="/xm_upload/${star.pic}" alt="">
  6. </a>
  7. <div style="clear: both;"></div>
  8. <div style="width: 234px;height: 85px;">
  9. <div style="width: 234px;height: 20px;line-height: 20px;text-align: center;font-size: 14px;font-family: Arial;
  10. color:red">
  11. ${star.pname}
  12. </div>
  13. <div style="width: 234px;height: 30px;line-height: 30px;text-align: center;color: #ff6700;font-size: 14px;font-family: Arial">
  14. <span style="color: #000">${star.price} &nbsp;起始价 </span>
  15. </div>
  16. </div>
  17. </div>
  18. </c:forEach>
  19. </c:if>

九、点击商品跳转到商品详情页面

思路

  1. 点击商品---跳转到服务器--- 根据商品的id查询出该商品---存到域对象中---跳转到product_detail.js中取出数据展示

代码实现:

index.jsp

  1. <a href="${pageContext.request.contextPath}/product?method=toProductDetail&pid=${star.pid}" target="_blank">
  2. <img class="time_min" style="width:234px;height: 234px;" src="/xm_upload/${star.pic}" alt="">
  3. </a>

Servlet:

  1. //跳转到商品详情页面
  2. protected void toProductDetail(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  3. //1、获取数据;
  4. String pid = request.getParameter("pid");
  5. //2、调用业务
  6. ProductService ps = new ProductService();
  7. Product p = ps.findByPid(pid);
  8. //3、结果的展示t.s
  9. request.setAttribute("product", p);
  10. request.getRequestDispatcher("/product_detail.jsp").forward(request, response);
  11. }

service:

  1. public Product findByPid(String pid) {
  2. // TODO Auto-generated method stub
  3. return pd.findByPid(pid);
  4. }

Dao:

  1. public Product findByPid(String pid) {
  2. String sql = "SELECT * FROM product WHERE pid = ?";
  3. try {
  4. return qr.query(sql, new BeanHandler<Product>(Product.class),pid);
  5. } catch (SQLException e) {
  6. // TODO Auto-generated catch block
  7. e.printStackTrace();
  8. return null;
  9. }
  10. }

product_detail.jsp 显示数据:

  1. <h3>商品名称:${product.pname}</h3>
  2. <p class="plus5_no3_right_p2">
  3. <span class="plus5_no3_right_span2">「${product.description}」</span>
  4. </p>

十、购物车逻辑分析

封装JavaBean的购物车分析图:

image.png

封装JavaBean对象:

CartItem:

  1. //购物项
  2. public class CartItem implements Serializable{
  3. //商品对象
  4. private Product product;
  5. //购买数量
  6. private int count;
  7. //小计
  8. private double subTotal;
  9. //计算小计
  10. public double getSubTotal() {
  11. return subTotal = (getProduct().getPrice()) * getCount();
  12. }
  13. ...
  14. }

Cart:

  1. public class Cart implements Serializable{
  2. /* 如何选用集合 :
  3. *
  4. * 需求:
  5. * 1、要求是有序的
  6. * 2、从购物车中移除商品方便
  7. *
  8. * 三大集合:
  9. * List:有序可以重复
  10. * Set:无序不可以重复
  11. * Map:key-value remove(key)
  12. *
  13. * */
  14. //key: pid value:CartItem
  15. private LinkedHashMap<String, CartItem> cartMap = new LinkedHashMap<String, CartItem>();
  16. //总价格
  17. private double total;
  18. //计算总价格
  19. public double getTotal() {
  20. total = 0.0;
  21. Set<String> keys = cartMap.keySet();
  22. for(String key:keys) {
  23. CartItem cartItem = cartMap.get(key);
  24. total += cartItem.getSubTotal();
  25. }
  26. return total;
  27. }
  28. }