• 家居网购项目


    大家好呀!我是小笙~ 该家居网购的技术栈是javaweb开发,我觉得这个是对之前学习的知识的一个总结和输出,是个很好的自我学习反馈的过程.

    家居网购项目

    家居网购-程序框架图

    使用分层模式: 分层的目的是为了解耦,降低代码的耦合度,有利项目的维护和升级

    image-20220514233424142

    三层架构MVC

    MVC 全称∶ Model 模型、View 视图、 Controller 控制器

    MVC 的理念是将软件代码拆分成为组件,单独开发,组合使用(目的还是为了解耦合), 也有很多落地的框架比如 SpringMVC

    • MVC 最早出现在 JavaEE 三层中的 Web 层,它可以有效的指导 WEB 层的代码如何有效 分离,单独工作
    • 后面业务复杂度越来越高, model 逐渐分层/组件化 (service + dao)

    image-20220514235826151

    项目准备

    需要引入的jar包

    image-20220528174844293

    程序框架图

    image-20220528173647527

    页面展示

    首页展示

    image-20220528174902781

    登录注册页面

    image-20220528174955287

    家居后台管理页面

    image-20220528175039263

    购物车页面

    image-20220528175118244

    订单生成页面

    image-20220528175157636

    功能实现

    注册功能

    1.设计用户表

    # 创建数据库
    DROP DATABASE IF EXISTS home_shopping; 
    CREATE DATABASE home_shopping; 
    USE home_shopping; 
    # 创建用户表
    CREATE TABLE member( 
    		`id` INT PRIMARY KEY AUTO_INCREMENT, # id
    		`username` VARCHAR(10) NOT NULL UNIQUE,  # 用户名
    		`password` VARCHAR(32) NOT NULL, # 密码
    		`email` VARCHAR(64), # 邮箱
    		`user_state` TINYINT NOT NULL DEFAULT 0 # 用户模式 0 会员 1 管理员 -1 未登录
    )CHARSET utf8 ENGINE INNODB;
    INSERT INTO member(`username`,`password`,`email`,`user_state`) VALUES('Al_tair',MD5('luo1234567'),'lns@qq.com',1);
    INSERT INTO member(`username`,`password`,`email`,`user_state`) VALUES('admins',MD5('1234567'),'1079936146@qq.com',0);
    SELECT * FROM member;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.Dao层对数据库的CRUD

    public interface MemberDao {
        /**
         * 添加会员用户信息
         */
        public boolean addUserInfo(Member member);
        /**
         * 查询是否有该用户名的会员用户
         */
        public boolean queryUserInfo(String username);
        /**
         * 查询有该用户名和密码的会员用户信息
         */
        public Member queryUserInfo(String username,String password);
    }
    // 备注:实现代码略,记得每次写完实现代码使用Junit测试
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.Service层对业务的操作

    public interface MemberService {
        /**
         * 注册用户
         */
        public boolean registerUser(Member member);
        /**
         * 是否有存在该用户
         */
        public boolean isExistUser(String username);
        /**
         * 用户登录
         */
        public Member login(String username,String password);
    }
    // 备注:实现代码略,记得每次写完实现代码使用Junit测试
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4.前端页面效果

    <!-- 截图部分重点 -->
    <div class="login-register-form">
        <!-- 错误提醒 -->
        <span class="errorMsg"
              style="float: right; font-weight: bold; font-size: 20pt; margin-left: 10px;">
        </span>
        <form action="memberServlet" method="post">
            <input type="hidden" name="action" value="register">
            <input type="text" id="username" name="username" placeholder="Username"/>
            <input type="password" id="password" name="password" placeholder="输入密码"/>
            <input type="password" id="repwd" name="repassword" placeholder="确认密码"/>
            <input name="email" id="email" placeholder="电子邮件" type="email"/>
            <input type="text" id="code" name="code" style="width: 50%"  placeholder="验证码"/>
            <img class="codeImgRegister" alt="" src="">
            <div class="button-box">
                <button type="submit" id="register-btn"><span>会员注册</span></button>
            </div>
        </form>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    image-20220516180009564

    5.前端页面校验(JQuery库)

    1. 验证用户名:必须字母,数字下划线组成,并且长度为 6 到 10 位

      /^[a-zA-Z0-9_]{6,10}$/
      
      • 1
    2. 验证密码:必须由字母,数字下划线组成,并且长度为 6 到 10 位

    3. 邮箱格式验证:常规验证即可 (正则表达式 )

      /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
      
      • 1
    4. 验证码:校验

      导入包

      image-20220523231754349

      表单重复提交情况:

      1. 提交完表单。服务器使用请求转发进行页面跳转。用户刷新(F5),会发起最后一 次的请求, 造成表单重复提交问题。解决:用重定向
      2. 用户正常提交,由于网络延迟等原因,未收到服务器的响应,这时,用户着急多 点了几次提交操作,也会造成表单重复提交。解决: 验证码
      3. 用户正常提交,服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提 交。也会造成表单重复提交,解决:验证码
      <!-- 点击校验码,更新校验码 -->
      $(".codeImgRegister").click(function(){
      	this.src="<%=request.getContextPath() + "/"%>kaptchaServlet?d=" + new Date();
      })
      
      • 1
      • 2
      • 3
      • 4
    5. 校验优化:Ajax异步请求

      <script type="text/javascript">    
          // Ajax异步请求:这里是登录用户的校验,同理注册也是可以的
          $("#LoginUsername").blur(function(){
              $.getJSON(
                  "memberServlet",
                  {
                      action:"IsExistUser",
                      username:$("#LoginUsername").val(),
                  },
                  function (data,state,XHttp) {
                      if(!data.IsExistUser){
                          $("span.errorMsg").text("用户名不存在!");
                      }else{
                          $("span.errorMsg").text("");
                      }
                  }
              )
          })
      </script>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19

    6.后端校验

    if(username == null || password == null || email == null || repassword == null){
        response.sendRedirect(getServletContext().getContextPath() + "/views/member/register_fail.jsp");
        return;
    }
    
    // 用户名格式校对
    String pattern = "^[a-zA-Z0-9_]{6,10}$";
    if(Pattern.matches(pattern,username)){
        System.out.println("用户名格式正确");
    }else{
        System.out.println("用户名格式不正确");
        response.sendRedirect(getServletContext().getContextPath() + "/views/member/register_fail.jsp");
        return;
    }
    
    // 密码格式校对
    pattern = "^[a-zA-Z0-9_]{6,10}$";
    if(Pattern.matches(pattern,password)){
        System.out.println("密码格式正确");
    }else{
        System.out.println("密码格式不正确");
        response.sendRedirect(getServletContext().getContextPath() + "/views/member/register_fail.jsp");
        return;
    }
    
    // 输入两次密码是否相同
    if(!password.equals(repassword)){
        System.out.println("输入两次密码不相同!");
        response.sendRedirect(getServletContext().getContextPath() + "/views/member/register_fail.jsp");
        return;
    }
    
    // 邮箱格式校对
    pattern = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?";
    if(Pattern.matches(pattern,email)){
        System.out.println("邮箱格式正确");
    }else{
        System.out.println("邮箱格式不正确");
        response.sendRedirect(getServletContext().getContextPath() + "/views/member/register_fail.jsp");
        return;
    }
    
    // 获取验证码
    HttpSession session = request.getSession();
    Object realCode = session.getAttribute(KAPTCHA_SESSION_KEY);
    // 立即删除session中该属性
    session.removeAttribute(KAPTCHA_SESSION_KEY);
    if(realCode == null || code == null || !code.equalsIgnoreCase((String)realCode)){
        System.out.println("验证码不正确");
        response.sendRedirect(getServletContext().getContextPath() + "/views/member/register_fail.jsp");
        return;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    7.注册页面后端需求分析

    1. 会员注册信息,前端验证通过后,提交给服务器

      • 如果用户名在数据库中已经存在,后台给出提示信息,并返回重新注册

      • 如果用户名没有在数据库中,完成注册,并返回注册成功的页面

    2. 注册密码为 md5 加密


    登录功能

    1.前端页面效果

    <div class="login-register-form">
        <!--  显示错误信息   -->
        <span style="font-size: 18pt;font-weight: bold;float: right;color: red">
            <span class="errorMsg"
                  style="float: right; font-weight: bold; font-size: 20pt; margin-left: 10px;">
            </span>
        </span>
        <form action="memberServlet" method="post">
            <input type="hidden" name="action" value="login">
            <input type="text" id="LoginUsername" name="username" value="${requestScope.get("username")}" placeholder="Username"/>
            <input type="password" name="password" placeholder="Password"/>
            <input type="text" id="code2" name="code" style="width: 50%" placeholder="验证码"/>  
            <img class="codeImgLogin" alt="" src="kaptchaServlet">
            <div class="button-box">
                <div class="login-toggle-btn">
                    <input type="checkbox"/>
                    <a class="flote-none" href="javascript:void(0)">Remember me</a>
                    <a href="#">Forgot Password?</a>
                </div>
                <button type="submit" id="login_btn"><span>Login</span></button>
            </div>
        </form>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    image-20220523231647402

    2.后端需求分析

    • 分别校验输入的用户名和密码是否符合格式

    • 通过用户名和密码去数据库查找数据

      • 如果找到数据,跳转到登录成功的页面

      • 如果没有找到数据或者用户名密码格式不对,都会返回登录页面并且显示

        image-20220516203314269

    3.优化Servlet,将处理请求和分发请求分开

    • 问题提出:其实不管是会员注册还是会员登录都是对会员用户的数据操作,但是却分出了两个Servlet,接下来我们尝试解决web层的优化

      • 方案一:通过隐藏域的值来判断是login还是register

        <input type="hidden" name="action" value="register">
        
        • 1
        String action = request.getParameter("action");
        if("register".equals(action)){
            RegisterServlet(request,response);
        }else if("login".equals(action)){
            LoginServlet(request,response);
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6

        问题存在:虽然分开了处理请求和分发请求,但是本质还是在一个Servlet操作,同时随着业务的拓展,会存在代码复用的问题

      • 方案二:反射 + 模板设计模式 + 动态绑定

        • 就是将接收http请求和分发请求交给父类BasicServlet,将处理请求交给子类

          public abstract class  BasicServlet extends HttpServlet {
              @Override
              protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                   // 注意action值要和方法名一致
                  String action = request.getParameter("action");
                  try {
                      Method declaredMethod = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class);
                      declaredMethod.invoke(request,response);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13

    后台家居管理

    1.设计家居表

    CREATE TABLE furn(
                `id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, # id
                `name` VARCHAR(32) NOT NULL DEFAULT ' ',  # 家居名
                `price` DECIMAL(11,2) NOT NULL, # 价格
                `vendor` VARCHAR(32) NOT NULL, # 制造商
                `sales` INT UNSIGNED NOT NULL, # 销量
                `inventory` INT UNSIGNED NOT NULL, # 库存
                `img_path` VARCHAR(256) NOT NULL # 存放图片的路径
    )CHARSET utf8 ENGINE INNODB 
    # 增
    INSERT INTO furns(`name`,`price`,`vendor`,`sales`,`inventory`,`img_path` ) VALUES ('Simple 北欧小桌',2030.00,'瑞典',668,20,'http://localhost:9999/homeShopping/shop-left-sidebar.html');
    # 改
    UPDATE furn SET `name`='花盆',`price`=200,`vendor`='中国',`sales` =20,
    		`inventory`=12,`img_path`='assets/images/product-image/2.jpg' WHERE `id` = 2;
    # 删	
    DELETE FROM furn WHERE `id` = 1; 
    # 查
    SELECT *FROM furns;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    实体类

    private Integer id;
    private String name;
    private BigDecimal price;
    private String vendor;
    private Integer sales;
    private Integer inventory;
    private String imgPath;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.设计Page分页数据模型

    public class Page<T> {
        public final static Integer PAGE_SIZE = 3;
        // 表示当前页号
        private Integer pageNo;
        // 表示每页显示最大记录数
        private Integer pageSize = PAGE_SIZE;
        // 表示当前页要显示的数据
        private List<T> items;
        // 表示共有多少页
        private Integer totalPage;
        // 表示共有多少记录
        private Integer totalRow;
        // 分页导航url
        private String url;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3.Dao对数据库的操作

    public interface FurnDao {
        /**
         * 查询所有家居信息
         */
        public List<Furn> queryAllFurns();
        /**
         * 通过id查询家居数据
         */
        public Furn queryFurnById(Integer id);
        /**
         * 添加家居
         */
        public boolean addFurns(Furn furn);
        /**
         * 删除家居
         */
        public boolean deleteFurnById(int id);
        /**
         * 修改家居
         */
        public boolean updateFurn(Furn furn);
        /**
         * 表示记录数量
         */
        public int rowNum();
        /**
         * 分页数据获取
         */
        public List<Furn> pageItems(int begin,int rowNum);
        /**
         * 表示记录数量(通过家具名过滤)
         */
        public int rowNumByName(String name);
        /**
         * 分页数据获取(通过家具名过滤)
         * @param begin 开始的记录位置 从0开始取
         * @param rowNum 取记录数
         */
        public List<Furn> pageItemsByName(int begin,int rowNum,String name);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    4.Service层对业务的操作

    public interface FurnService {
        /**
         * 通过id查询家居数据
         */
        public Furn queryFurnById(Integer id);
        /**
         * 显示家居
         */
        public List<Furn> showFurns();
        /**
         * 添加家居
         */
        public boolean addFurns(Furn furn);
        /**
         * 删除家居
         */
        public boolean deleteFurnById(int id);
        /**
         * 修改家居
         */
        public boolean updateFurn(Furn furn);
        /**
         *  家居显示分页管理
         * @param pageNo 页号
         * @param pageSize 一个页面最大记录数
         */
        public Page<Furn> pageManage (int pageNo,int pageSize);
        /**
         *  家居显示分页管理(通过家具名过滤)
         * @param pageNo 页号
         * @param pageSize 一个页面最大记录数
         */
        public Page<Furn> pageManageByName (int pageNo,int pageSize,String name);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    分页算法

    @Override
    public Page<Furn> pageManage(int pageNo,int pageSize) {
        Page<Furn> page = new Page<>();
        page.setPageNo(pageNo);
    
        page.setPageSize(pageSize);
    
        int totalRow = furns.rowNum();
        page.setTotalRow(totalRow);
    
        int totalPage = (int)Math.ceil(totalRow * 1.0 / pageSize);
        page.setTotalPage(totalPage);
    
        int begin = pageSize*(pageNo-1);
        page.setItems(furns.pageItems(begin, (totalRow-begin)/pageSize>0?pageSize:totalRow%pageSize));
        page.setUrl("url");
        return page;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    5.后台家居管理页面

    <!-- 家居显示 -->
    <c:forEach items="${requestScope.get('page').items}" var="furn">
        <tr>
            <td class="product-thumbnail">
                <a href="#"><img class="img-responsive ml-3" src="${furn.imgPath}"
                                 alt=""/></a>
            </td>
            <td class="product-name"><a href="#">${furn.name}</a></td>
            <td class="product-name"><a href="#">${furn.vendor}</a></td>
            <td class="product-price-cart"><span class="amount">${furn.price}</span></td>
            <td class="product-quantity">
                ${furn.sales}
            </td>
            <td class="product-quantity">
                ${furn.inventory}
            </td>
            <td class="product-remove">
                <a class="updateFurn" href="views/furn/furn_update.jsp?id=${furn.id}&name=${furn.name}&price=${furn.price}&vendor=${furn.vendor}&sales=${furn.sales}&inventory=${furn.inventory}&imgPath=${furn.imgPath}
    &pageNo=${requestScope.get("page").pageNo}&furnName=${requestScope.name}">
                    <i class="icon-pencil"></i>
                </a>
                <a class="deleteFurn" href="manage/furnServlet?action=deleteFurn&id=${furn.id}&pageNo=${requestScope.get("page").pageNo}&furnName=${requestScope.name}"><i class="icon-close"></i></a>
            </td>
        </tr>
    </c:forEach>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    分页显示代码

    <ul>
        <li><a href="${requestScope.page.url}">首页</a></li>
        <c:if test="${requestScope.get('page').pageNo > 1}">
            <li><a href="${requestScope.page.url}&pageNo=${requestScope.get('page').pageNo-1}">上页</a></li>
        </c:if>
    
        <%--设置显示分页号数--%>
        <%--页面总数大于5的时候,显示5个页码--%>
        <c:if test="${requestScope.get('page').totalPage > 5}">
            <c:set var="begin" value="${requestScope.get('page').pageNo-2}"/>
            <c:set var="end" value="${requestScope.get('page').pageNo+2}"/>
        </c:if>
        <%--页面位置在前面2个--%>
        <c:if test="${requestScope.get('page').pageNo <= 3}">
            <c:set var="begin" value="1"/>
            <c:set var="end" value="5"/>
        </c:if>
        <%--页面位置在后面2个--%>
        <c:if test="${(requestScope.get('page').totalPage - requestScope.get('page').pageNo) <= 3}">
            <c:set var="begin" value="${requestScope.get('page').totalPage-4}"/>
            <c:set var="end" value="${requestScope.get('page').totalPage}"/>
        </c:if>
        <%--页面总数小于5的时候,默认全部显示--%>
        <c:if test="${requestScope.get('page').totalPage  <= 5}">
            <c:set var="begin" value="1"/>
            <c:set var="end" value="${requestScope.get('page').totalPage}"/>
        </c:if>
    
        <%--循环遍历显示页号数--%>
        <c:forEach begin="${begin}" end="${end}" var="pageNum">
            <c:if test="${pageNum == requestScope.get('page').pageNo}">
                <li><a class="active" href="${requestScope.page.url}&pageNo=${pageNum}">${pageNum}</a></li>
            </c:if>
            <c:if test="${pageNum != requestScope.get('page').pageNo}">
                <li><a href="${requestScope.page.url}&pageNo=${pageNum}">${pageNum}</a></li>
            </c:if>
        </c:forEach>
    
        <c:if test="${requestScope.get('page').pageNo < requestScope.get('page').totalPage}">
            <li><a href="${requestScope.page.url}&pageNo=${requestScope.get('page').pageNo+1}">下页</a></li>
        </c:if>
        <li><a href="${requestScope.page.url}&pageNo=${requestScope.get('page').totalPage}">末页</a></li>
        <li><a>共${requestScope.get('page').totalPage}页</a></li>
        <li><a>共${requestScope.get('page').totalRow}记录</a></li>
    </ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    image-20220530212956926

    6.控制层对家居的增删改查

    BeanUtils自动封装Bean

    1. BeanUtils 工具类,它可以一次性的把所有请求的参数注入到 JavaBean 中
    2. BeanUtils 工具类,经常用于把 Map 中的值注入到 JavaBean 中,或者是对象属性值的拷贝操作
    3. 需要导入需要的 jar 包: commons-beanutils-1.8.0.jar commons-logging-1.1.1.jar
    // 使用工具包前
    String name = request.getParameter("name");
    String price = request.getParameter("price");
    String vendor = request.getParameter("vendor");
    String sales = request.getParameter("sales");
    String inventory = request.getParameter("inventory");
    String imgPath = request.getParameter("imgPath");
    try {
        Furn furn = new Furn(name, new BigDecimal(price), vendor,
                             Integer.valueOf(sales), Integer.valueOf(inventory), img);
        furns.addFurns(furn);
    }catch (Exception e){
        request.setAttribute("errorMsg","添加家居数据格式错误!");
        request.getRequestDispatcher("/views/furn/furn_add.jsp").forward(request,response);
        return;
    }
    
    // 使用工具包之后
    //1.会使用工具类 DataUtils 来完成自动封装 JavaBean 
    //2.注意表单提交的数据对应的 name 需要和 JavaBean 的属性名保持一致
    Furn furn = new Furn();
    try {
        // 本质:通过反射来为Javabean对象set方法添加属性值
        BeanUtils.populate(furn,request.getParameterMap());
        furns.addFurns(furn);
    }catch (Exception e){
        request.setAttribute("errorMsg","添加家居数据格式错误!");
        request.getRequestDispatcher("/views/furn/furn_add.jsp").forward(request,response);
        return;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    搜索框
    <div class="header_account_list">
        <a href="javascript:void(0)" class="header-action-btn search-btn"><i class="icon-magnifier"></i></a>
        <div class="dropdown_search">
            <form class="action-form" action="customerFurnServlet">
                <input type="hidden" name="action" value="customerFurnByName">
                <input class="form-control" name="name" placeholder="输入家居名搜索" type="text">
                <button class="submit" type="submit"><i class="icon-magnifier"></i></button>
            </form>
        </div>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    image-20220530215259802

    通过page对象的url来携带搜索的家具名,起到点击分页栏,仍旧处在搜索结果的条件下

    protected void customerFurnByName(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 页号
        String pageNo = request.getParameter("pageNo");
        // 搜索框内容:家居名
        String name = request.getParameter("name");
        // session记录登录情况以及身份
        HttpSession session = request.getSession();
        Object username = session.getAttribute("username");
        Object userState = session.getAttribute("userState");
    
        if(username == null){
            username = "登录|注册";
            userState = -1;
        }
        if(name == null){
            name = "";
        }
        if(pageNo == null){
            pageNo = "1";
        }
        // 分页(根据家具名来分页搜索)
        Page<Furn> pages = furns.pageManageByName(Integer.parseInt(pageNo), 4,name);
        StringBuffer url = new StringBuffer("customerFurnServlet?action=customerFurnByName");
        if(!"".equals(name)){
            url.append("&name=").append(name);
        }else{
            url.append("&name=").append("");
        }
        pages.setUrl(url.toString());
        request.setAttribute("page",pages);
        request.setAttribute("username",username);
        request.setAttribute("userState",userState);
        request.getRequestDispatcher("/views/customer/index.jsp").forward(request,response);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    添加家居
    <tr>
        <td class="product-thumbnail">
            <input type="hidden" name="imgPath" value="assets/images/product-image/1.jpg">
            <a href="#"><img class="img-responsive ml-3" src="assets/images/product-image/1.jpg" alt=""/></a>
        </td>
        <td class="product-name"><input name="name" style="width: 60%" type="text" value=""/></td>
        <td class="product-name"><input name="vendor" style="width: 90%" type="text" value=""/></td>
        <td class="product-price-cart"><input name="price" style="width: 90%" type="text" value=""/></td>
        <td class="product-quantity">
            <input name="sales" style="width: 90%" type="text" value=""/>
        </td>
        <td class="product-quantity">
            <input name="inventory" style="width: 90%" type="text" value=""/>
        </td>
        <td>
            <input type="submit" style="width: 90%;background-color: silver;border: silver;border-radius: 20%;" value="添加家居"/>
        </td>
    </tr>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20220518211524375

    protected void addFurn(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pageNo = request.getParameter("pageNo");
        Furn furn = new Furn();
        try {
            BeanUtils.populate(furn,request.getParameterMap());
        }catch (Exception e){
            request.setAttribute("errorMsg","添加家居数据格式错误!");
            request.getRequestDispatcher("/views/furn/furn_add.jsp").forward(request,response);
            return;
        }
        furns.addFurns(furn);
        response.sendRedirect(getServletContext().getContextPath() + "/manage/furnServlet?action=showPageDisplayByName&pageNo=" + pageNo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    删除家居

    前端判断是否删除

    <script type="text/javascript">
        $(function(){
            $("a.deleteFurn").click(function(){
                var furnName = $(this).parent().parent().find("td:eq(1)").text();
                if(confirm("确定删除家居【"+ furnName + "】?")){
                    return true;
                }
                return false;
            })
        })
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    image-20220519111319741

    protected void deleteFurn(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pageNo = request.getParameter("pageNo");
        String id = request.getParameter("id");
        String name = URLEncoder.encode(request.getParameter("furnName"), "utf-8");
        boolean deleteFlag = false;
        try {
            // 通过id删除家居
            deleteFlag = furns.deleteFurnById(Integer.parseInt(id));
        }catch (Exception e){
            throw new RuntimeException();
        }
        System.out.println(deleteFlag?"删除成功":"删除失败");
        response.sendRedirect(getServletContext().getContextPath() + "/manage/furnServlet?action=showPageDisplayByName&name=" + name + "&pageNo=" + pageNo);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    修改家居
    <tr>
        <td class="product-thumbnail">
            <div id="pic">
                <img id="prevView" name="imgPath"  class="img-responsive ml-3" src=<%=request.getParameter("imgPath")%> alt=""/>
                <input id="upload" type="file" name="pic" onchange="prev(this)"/>
            </div>
        </td>
        <td class="product-name"><input name="name" style="width: 60%" type="text" value=<%=request.getParameter("name")%>></td>
        <td class="product-name"><input name="vendor" style="width: 90%" type="text" value=<%=request.getParameter("vendor")%>></td>
        <td class="product-price-cart"><input name="price" style="width: 90%" type="text" value=<%=request.getParameter("price")%>></td>
        <td class="product-quantity">
            <input name="sales" style="width: 90%" type="text" value=<%=request.getParameter("sales")%>>
        </td>
        <td class="product-quantity">
            <input name="inventory" style="width: 90%" type="text" value=<%=request.getParameter("inventory")%>>
        </td>
        <td>
            <input type="submit" style="width: 90%;background-color: silver;border: silver;border-radius: 20%;" value="修改家居"/>
        </td>
    </tr>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    image-20220519111621282

    <!-- furn_manage.jsp -->
    <a class="updateFurn" href="views/furn/furn_update.jsp?id=${furn.id}&name=${furn.name}&price=${furn.price}                            &vendor=${furn.vendor}&sales=${furn.sales}&inventory=${furn.inventory}&imgPath=${furn.imgPath}">
        <i class="icon-pencil"></i>
    </a>
    
    
    <!-- furn_update.jsp -->
    <tr>
        <td class="product-thumbnail">
            <input type="hidden" name="imgPath" value="assets/images/product-image/default.jpg">
            <a href="#"><img class="img-responsive ml-3" src=<%=request.getParameter("imgPath")%>
                             alt=""/></a>
        </td>
        <td class="product-name"><input name="name" style="width: 60%" type="text" value=<%=request.getParameter("name")%>></td>
        <td class="product-name"><input name="vendor" style="width: 90%" type="text" value=<%=request.getParameter("vendor")%>></td>
        <td class="product-price-cart"><input name="price" style="width: 90%" type="text" value=<%=request.getParameter("price")%>></td>
        <td class="product-quantity">
            <input name="sales" style="width: 90%" type="text" value=<%=request.getParameter("sales")%>>
        </td>
        <td class="product-quantity">
            <input name="inventory" style="width: 90%" type="text" value=<%=request.getParameter("inventory")%>>
        </td>
        <td>
            <input type="submit" style="width: 90%;background-color: silver;border: silver;border-radius: 20%;" value="修改家居"/>
        </td>
    </tr>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    购物车功能

    1.设计购物车数据模型

    // 数据库种每一件商品的信息
    public class CarItem {
        private Integer id;
        private String name;
        private BigDecimal singlePrice;
        private Integer count;
        private BigDecimal singleTotalPrice;
        private String imgPath;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    /**
     * 含有多个CarItem,用来管理购物车内多个商品
     */
    public class Cart {
    
        /**
         * 存储 id 对应的商品
         */
        private Map<Integer,CarItem> items = new HashMap<>();
        /**
         * 用来有序存放加入购物车的顺序
         */
        private List<CarItem> itemsList = new ArrayList<>();
    
        public List<CarItem> getItemsList() {
            return itemsList;
        }
    
        /**
         * 添加商品到购物车
         */
        public void addItem(CarItem carItem){
            Integer id = carItem.getId();
            CarItem originalCarItem = items.get(id);
            if(originalCarItem == null){ // 购物车内没有相同的该商品
                items.put(id,carItem);
                itemsList.add(carItem);
            }else{
                originalCarItem.setCount(carItem.getCount() + originalCarItem.getCount());
                originalCarItem.setSingleTotalPrice(carItem.getSingleTotalPrice().add(originalCarItem.getSingleTotalPrice()));
            }
        }
    
        /**
         * 返回商品的总金额
         */
        public BigDecimal getCartItemsPrice(){
            BigDecimal totalPrice = new BigDecimal(0.0);
            Set<Integer> itemsId = items.keySet();
            for (Integer id : itemsId) {
                totalPrice = totalPrice.add((items.get(id)).getSingleTotalPrice());
            }
            return totalPrice;
        }
    
        /**
         * 获取商品的总数
         */
        public Integer getCartItemsCount(){
            Integer totalCount = 0;
            if(items == null){
                return totalCount;
            }
            Set<Integer> itemsId = items.keySet();
            for (Integer id : itemsId) {
                totalCount += items.get(id).getCount();
            }
            return totalCount;
        }
    
        /**
         * 返回指定商品列表
         */
        public List<CarItem> listItem(Integer begin,Integer end){
            if(items == null){
                return null;
            }
            List<CarItem> carItems = new ArrayList<>();
            for(int i = begin;i<begin+end;i++){
                carItems.add(itemsList.get(i));
            }
            return carItems;
        }
    
        /**
         * 购物车商品分页管理
         */
        public Page<CarItem> pageManageCartItems(int pageNo, int pageSize) {
            Page<CarItem> page = new Page<>();
            page.setPageNo(pageNo);
    
            page.setPageSize(pageSize);
    
            int totalRow = itemsList.size();
            page.setTotalRow(totalRow);
    
            int totalPage = (int)Math.ceil(totalRow * 1.0 / pageSize);
            page.setTotalPage(totalPage);
    
            int begin = pageSize*(pageNo-1);
            page.setItems(listItem(begin, (totalRow-begin)/pageSize>0?pageSize:totalRow%pageSize));
            page.setUrl("url");
            return page;
        }
    
        /**
         * 更新商品的数量
         */
        public void updateItem(Integer id,Integer count){
            if(id == null || count == null){
                return;
            }
            CarItem originalCarItem = items.get(id);
            if(originalCarItem == null){
                return;
            }
            if(count == 0){
                deleteItem(id);
                return;
            }
            originalCarItem.setCount(count);
            originalCarItem.setSingleTotalPrice(new BigDecimal(originalCarItem.getCount()).multiply(originalCarItem.getSinglePrice()));
        }
    
        /**
         * 删除某个商品
         */
        public void deleteItem(Integer id){
            CarItem originalCarItem = items.get(id);
            if(originalCarItem == null){
                return;
            }
            for (CarItem carItem : itemsList) {
                if(carItem.getId().equals(id)){
                    itemsList.remove(carItem);
                    items.remove(id);
                    return;
                }
            }
        }
    
        /**
         * 清空购物车
         */
        public void deleteCart(){
            items = new HashMap<>();
            itemsList = new ArrayList<>();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139

    2.购物车显示页面

    <c:forEach items="${requestScope.pages.items}" var="cartItem">
        <tr>
            <td class="product-thumbnail">
                <a><img class="img-responsive ml-3" src="${cartItem.imgPath}" alt=""/></a>
            </td>
            <td class="product-name"><a>${cartItem.name}</a></td>
            <td class="product-price-cart"><span class="amount">¥${cartItem.singlePrice}</span></td>
            <td class="product-quantity">
                <div class="cart-plus-minus">
                    <input readonly="true" ItemId="${cartItem.id}" class="cart-plus-minus-box" id="count" type="text" name="qtybutton" value=${cartItem.count} >
                </div>
            </td>
            <td class="product-subtotal">¥${cartItem.singleTotalPrice}</td>
            <td class="product-remove">
                <a id="cleanCartItem" href="cart/cartServlet?action=deleteCartItem&id=${cartItem.id}&pageNo=${requestScope.pages.pageNo}"><i class="icon-close"></i></a>
            </td>
        </tr>
    </c:forEach>
    <div class="cart-shiping-update-wrapper">
        <c:if test="${sessionScope.cart.getCartItemsCount() != 0}">
            <h4>共${sessionScope.cart.getCartItemsCount()}件商品 总价${sessionScope.cart.getCartItemsPrice()}元</h4>
        </c:if>
        <h4></h4><h4></h4><h4></h4><h4></h4><h4></h4>
        <div class="cart-shiping-update">
            <a href="order/orderServlet?action=generateOrder">购 物 车 - 生 成 订 单</a>
        </div>
        <div class="cart-clear">
            <button type="submit">继 续 购 物</button>
            <a href="cart/cartServlet?action=deleteCart" id="cleanCart">清 空 购 物 车</a>
        </div>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    image-20220531235206305

    3.对购物车的增删操作

    /**
      * 清空购物车
      */
    protected void deleteCart(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        Object cart = session.getAttribute("cart");
        if(cart != null){
            ((Cart)cart).deleteCart();
        }
        Page<CarItem> pages = ((Cart)cart).pageManageCartItems(1,4);
        request.setAttribute("pages",pages);
        request.getRequestDispatcher("/views/cart/cart.jsp").forward(request,response);
    }
    
    /**
      * 在购物车里删除某个商品
      */
    protected void deleteCartItem(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pageNo = request.getParameter("pageNo");
        String id = request.getParameter("id");
    
        HttpSession session = request.getSession();
        Object originalCart = session.getAttribute("cart");
        Cart cart = null;
        if(originalCart == null){
            cart = new Cart();
        }else{
            cart = (Cart) originalCart;
        }
        if(pageNo == null){
            pageNo = "1";
        }
    
        cart.deleteItem(Integer.parseInt(id));
        Page<CarItem> pages = cart.pageManageCartItems(Integer.parseInt(pageNo),4);
        request.setAttribute("pages",pages);
        request.getRequestDispatcher("/views/cart/cart.jsp").forward(request,response);
    }
    
    /**
      * 分页展示商品
      */
    protected void showCartPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pageNo = request.getParameter("pageNo");
        HttpSession session = request.getSession();
        Object originalCart = session.getAttribute("cart");
        Cart cart = null;
        if(originalCart == null){
            cart = new Cart();
        }else{
            cart = (Cart) originalCart;
        }
        if(pageNo == null){
            pageNo = "1";
        }
        Page<CarItem> pages = cart.pageManageCartItems(Integer.parseInt(pageNo),4);
        request.setAttribute("pages",pages);
        request.getRequestDispatcher("/views/cart/cart.jsp").forward(request,response);
    }
    
    /**
      * 更新商品数据(+ - 商品数量)
      */
    protected void updateCartPage(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String pageNo = request.getParameter("pageNo");
        String id = request.getParameter("id");
        String count = request.getParameter("count");
    
        HttpSession session = request.getSession();
        Object originalCart = session.getAttribute("cart");
        Cart cart = null;
        if(originalCart == null){
            cart = new Cart();
        }else{
            cart = (Cart) originalCart;
        }
        if(pageNo == null){
            pageNo = "1";
        }
    
        cart.updateItem(Integer.parseInt(id),Integer.parseInt(count));
        Page<CarItem> pages = cart.pageManageCartItems(Integer.parseInt(pageNo),4);
        request.setAttribute("pages",pages);
        request.getRequestDispatcher("/views/cart/cart.jsp").forward(request,response);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    首页家居功能

    1.首页页面效果

    <c:forEach items="${requestScope.get('page').items}" var="furn">
        <div class="col-lg-3 col-md-6 col-sm-6 col-xs-6 mb-6" data-aos="fade-up" data-aos-delay="200">
            <!-- Single Prodect -->
            <div class="product">
                <div class="thumb">
                    <a href="#" class="image">
                        <img src=${furn.imgPath} alt="Product"/>
                        <img class="hover-image" src="assets/images/product-image/5.jpg" alt="Product"/>
                    </a>
                    <span class="badges"> <span class="new">New</span> </span>
                    <div class="actions">
                        <a href="#" class="action wishlist" data-link-action="quickview"
                           title="Quick view" data-bs-toggle="modal" data-bs-target="#exampleModal">
                            <i class="icon-size-fullscreen"></i>
                        </a>
                    </div>
                    <form action="#" method="get">
                        <input name="pageNo" type="hidden" value=${requestScope.get('page').pageNo}>
                        <input name="action" type="hidden" value="addItem">
                        <input name="id" type="hidden" value="${furn.id}">
                        <input name="name" type="hidden" value="${furn.name}">
                        <input name="singlePrice" type="hidden" value="${furn.price}">
                        <input name="count" type="hidden" value="1">
                        <input name="name" type="hidden" value="${furn.name}">
                        <input name="singleTotalPrice" type="hidden" value="${furn.price}">
                        <input name="imgPath" type="hidden" value="${furn.imgPath}">
                        <!-- 根据存货判断是否能添加到购物车-->
                        <c:if test="${furn.inventory == 0}">
                            <button title="Add To Cart" furnInventory="0" class="add-to-cart" type="button">
                                Add To Cart【暂时缺货】
                            </button>
                        </c:if>
                        <c:if test="${furn.inventory > 0}">
                            <button furnId="${furn.id}" furnInventory="${furn.inventory}" title="Add To Cart" class="add-to-cart" type="button">
                                Add To Cart
                            </button>
                        </c:if>
                    </form>
                </div>
                <div class="content">
                    <h5 class="title">
                        <a href="shop-left-sidebar.html">${furn.name} </a></h5>
                    <span class="price">
                        <span class="new">家居: ${furn.name}</span>
                    </span>
                    <span class="price">
                        <span class="new">厂商: ${furn.vendor}</span>
                    </span>
                    <span class="price">
                        <span class="new">价格: ¥${furn.price}</span>
                    </span>
                    <span class="price">
                        <span class="new">销量: ${furn.sales}</span>
                    </span>
                    <span class="price">
                        <span class="new">库存: ${furn.inventory}</span>
                    </span>
                </div>
            </div>
        </div>
    </c:forEach>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    image-20220530215846731

    protected void showPageDisplayByName(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 页号
        String pageNo = request.getParameter("pageNo");
        // 搜索框内容:家居名
        String name = request.getParameter("name");
        if(name == null){
            name = "";
        }
        if(pageNo == null){
            pageNo = "1";
        }
        // 分页(根据家具名来分页搜索)
        Page<Furn> pages = furns.pageManageByName(Integer.parseInt(pageNo), Page.PAGE_SIZE,name);
        StringBuffer url = new StringBuffer("manage/furnServlet?action=showPageDisplayByName");
        if(!"".equals(name)){
            url.append("&name=").append(name);
        }else{
            url.append("&name=").append("");
        }
        pages.setUrl(url.toString());
        request.setAttribute("page",pages);
        request.setAttribute("name",name);
        request.getRequestDispatcher("/views/manage/furn_manage.jsp").forward(request,response);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2.点击首页商品加入购物车(Ajax请求)

    /**
      * 通过Ajax请求来添加商品
      */
    protected void AddItemByAjax(HttpServletRequest request, HttpServletResponse response) throws InvocationTargetException, IllegalAccessException, IOException {
        HttpSession session = request.getSession();
        Object originalCart = session.getAttribute("cart");
        Cart cart = null;
        if(originalCart == null){
            cart = new Cart();
        }else{
            cart = (Cart) originalCart;
        }
    
        // 添加的商品数据生成商品对象
        int id = Integer.parseInt(request.getParameter("id"));
        CarItem carItem = new CarItem();
        Furn furn = furnService.queryFurnById(id);
        carItem.setId(furn.getId());
        carItem.setName(furn.getName());
        carItem.setCount(1);
        carItem.setImgPath(furn.getImgPath());
        carItem.setSinglePrice(furn.getPrice());
        carItem.setSingleTotalPrice(furn.getPrice());
        cart.addItem(carItem);
        session.setAttribute("cart",cart);
    
        Gson gson = new Gson();
        HashMap<String, Object> map = new HashMap<>();
        map.put("carItemNum",cart.getCartItemsCount());
        response.getWriter().write(gson.toJson(map));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    订单管理

    1.设计订单表以及细节订单

    # 订单表
    CREATE TABLE `order`(
    	  	`id`  VARCHAR(32) NOT NULL UNIQUE, # 订单号
    		`create_time` DATETIME NOT NULL,  # 订单日期
        	`price`  DECIMAL(11,2) NOT NULL, # 价格
    		`status` VARCHAR(16) NOT NULL, # 订单状态
    		`member_id`INT NOT NULL # 关联用户id
    )CHARSET utf8 ENGINE INNODB;
    INSERT INTO `order`(`id`,`create_time`,`price`,`status`,`member_id`) 
    VALUES('12',NOW(),203,'未发货',3);
    SELECT `id`,`create_time` AS createTime,`price`,`status`,`member_id` AS memberId FROM `order`;
    SELECT *FROM `order`;
    
    # 订单细节表(属于订单表)
    CREATE TABLE `order_detail`(
    		`id` INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, #id
    	     `name` VARCHAR(32) NOT NULL, # 家居名
             `price` DECIMAL(11,2) NOT NULL, # 价格
    		`count` INT UNSIGNED NOT NULL, # 数量
    		`total_price` DECIMAL(11,2) NOT NULL, # 金额
    		`order_id` VARCHAR(32) NOT NULL # 订单号
    )CHARSET utf8 ENGINE INNODB; 
    INSERT INTO `order_detail`(`name`,`price`,`count`,`total_price`,`order_id`) VALUES('123',123.0,12,456,"456789");
    SELECT *FROM `order_detail` WHERE `order_id` = 456789;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    2.Dao对数据库的操作

    public interface OrderDao {
        /**
         * 添加订单
         */
        public boolean saveOrder(Order order);
    
        /**
         * 查询所有订单
         */
        public List<Order> listOrder();
    }
    
    public interface OrderItemDao {
        /**
         * 存订单详细信息
         */
        public boolean saveOrderItem(OrderItem orderItem);
        /**
         * 生成对应订单的商品列表哦
         */
        public List<OrderItem> listOrderItem(String orderId);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    3.Service对业务的操作

    public interface OrderService {
        /**
         * 保存订单数据
         *
         * @param cart 购物车
         * @param memberId 登录用户id
         * @return 订单号
         */
        public String saveOrder(Cart cart,int memberId);
        /**
         * 订单列表
         */
        public List<Order> listOrder();
        /**
         * 商品列表
         */
        public List<OrderItem> listOrderItem(String orderId);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    4.订单页面以及订单细节页面

    订单页面

    <c:forEach items="${requestScope.orders}" var="order">
        <tr>
            <td class="product-name">${order.id}</td>
            <td class="product-name">${order.createTime}</td>
            <td class="product-price-cart"><span class="amount">${order.price}</span></td>
            <td class="product-name"><a href="#">${order.status}</a></td>
            <td class="product-remove">
                <a href="order/orderServlet?action=listOrderItem&orderId=${order.id}" ><i class="icon-eye"></i></a>
            </td>
        </tr>
    </c:forEach>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    image-20220601210655756

    订单细节页面

    c:forEach items="${requestScope.orderItems}" var="orderItem">
    <tbody>
        <tr>
            <td class="product-name"><a>${orderItem.name}</a></td>
            <td class="product-price-cart"><span class="amount">$${orderItem.price}</span></td>
            <td class="product-quantity">${orderItem.count}</td>
            <td class="product-subtotal">$${orderItem.totalPrice}</td>
        </tr>
    </tbody>
    </c:forEach>
    <div class="col-lg-12">
        <div class="cart-shiping-update-wrapper">
            <h4>共${requestScope.totalCount}件商品 总价${requestScope.totalPrice}元</h4>
            <div class="cart-clear">
                <a href="#">继 续 购 物</a>
            </div>
        </div>
    </div>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    image-20220601210712601

    5.控制层对订单的数据操作

    @WebServlet(name = "OrderServlet",urlPatterns = {"/order/orderServlet"})
    public class OrderServlet extends BasicServlet {
        OrderService orderService = new OrderServiceImpl();
        MemberService memberServlet = new MemberServiceImpl();
        FurnService furnService = new FurnServiceImpl();
        
        /**
         * 显示订单
         */
        protected void listOrder(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            List<Order> orders = orderService.listOrder();
            request.setAttribute("orders",orders);
            request.getRequestDispatcher("/views/order/order.jsp").forward(request,response);
        }
        
        /**
         * 显示订单细节
         */
        protected void listOrderItem (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String orderId = request.getParameter("orderId");
            List<OrderItem> orderItems = orderService.listOrderItem(orderId);
            int totalCount = 0;
            BigDecimal totalPrice = new BigDecimal(0.0);
            for (OrderItem orderItem : orderItems) {
                totalCount += orderItem.getCount();
                totalPrice = totalPrice.add(orderItem.getTotalPrice());
            }
            request.setAttribute("orderItems",orderItems);
            request.setAttribute("totalCount",totalCount);
            request.setAttribute("totalPrice",totalPrice);
            request.getRequestDispatcher("/views/order/order_detail.jsp").forward(request,response);
        }
    
        /**
         * 生成一个订单
         */
        protected void generateOrder(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
            HttpSession session = request.getSession();
            Object username = session.getAttribute("username");
            Object password = session.getAttribute("password");
    
            if(username == null){
                System.out.println("用户未登录!");
                response.sendRedirect(getServletContext().getContextPath() + "/views/member/login.jsp");
                return;
            }
            Object originalCart = session.getAttribute("cart");
            if(originalCart == null){
                System.out.println("购物车为空!");
                response.sendRedirect(request.getHeader("Referer"));
                return;
            }
            Cart cart = null;
            cart = (Cart)originalCart;
            // 遍历购物车的商品数量有没有超过该商品的库存
            List<CarItem> itemsList = cart.getItemsList();
            for (CarItem carItem : itemsList) {
               if(carItem.getCount() > furnService.queryFurnById(carItem.getId()).getInventory()){
                   System.out.println("有商品已经超出库存限制!");
                   response.sendRedirect(request.getHeader("Referer"));
                   return;
               }
            }
            // 这里通过用户名和密码查找用户并不是登录(Service层名字设计有问题)
            Member member = memberServlet.login((String) username, (String) password);
            String orderId = orderService.saveOrder(cart, member.getId());
            session.setAttribute("cart",null);
            session.setAttribute("orderId",orderId);
            response.sendRedirect(getServletContext().getContextPath() + "/views/order/checkout.jsp");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
  • 相关阅读:
    Dropout回顾
    Kafka消费者使用案例
    使用逻辑分析仪处理IIC信号
    用AI模型实现两种图像是否相同的验证
    教育src漏洞挖掘-2022-白帽必挖出教程
    通过Keil如何查看MCU的RAM与ROM使用情况
    归并排序(java)
    java部署教程
    Nexus 私服上传 jar 包 Connection rest
    Prometheus+Grafana监控系统
  • 原文地址:https://blog.csdn.net/Al_tair/article/details/125447476