一、批量删除
    需要注意的点:
    如何将页面上选中的checkbox提交给servlet?
    页面端: name value
    <input type=”checkbox” name=”ids” value=”${cus.id}”/>
    将table包裹一层form表单

    1. <!--form表单的提交只提交input输入框内的值-->
    2. <form id="form" action="${pageContext.request.contextPath}/batchDel" method="post">
    3. <table class="table table-bordered table-hover">
    4. <thead>
    5. <tr>
    6. <th><input type="checkbox" id="checkAll"/></th>
    7. <th>序号</th>
    8. <th>客户邮箱</th>
    9. <th>客户登记</th>
    10. <th>过期时间</th>
    11. <th>编辑</th>
    12. <th>删除</th>
    13. </tr>
    14. </thead>
    15. <tbody>
    16. <c:if test="${not empty customerList}">
    17. <c:forEach items="${customerList}" var="cus" varStatus="vvv">
    18. <tr>
    19. <td scope="row"><input type="checkbox" name="ids" value="${cus.id}"/></td>
    20. <td>${vvv.count}</td>
    21. <td>${cus.address}</td>
    22. <td>${cus.levelName}</td>
    23. <td>${cus.overTimeStr}</td>
    24. <td><a href="#"> <span class="glyphicon glyphicon-edit"></span></a></td>
    25. <td><a onclick="delConfirm(${cus.id})"> <span class="glyphicon glyphicon-trash"></span></a></td>
    26. </tr>
    27. </c:forEach>
    28. </c:if>
    29. </tbody>
    30. </table>
    31. </form>

    点击“批量删除”按钮,通过jquery提交表单

    function batchDel(){
                if(choiceNum!=0){
                    Confirm.show('溫馨提示', '您确定要删除这'+choiceNum+'条记录吗?', {
                        'Delete' : {
                            'primary' : true,
                            'callback' : function() {
                                // 此处进行删除操作  此处只需要提交表单即可
                                $("#form").submit();
                            }
                        }
                    });
                }else{
                    alert("请选择您要删除的数据!");
                }
    
    }
    

    后台如何获取提交的checkbox数据呢?
    String[] ids = req.getParameterValues(“ids”);
    Dao层通过jdbcTemplate批量删除方法进行操作

    public int batchDel(String[] ids) {
            String sql ="delete from customer where id=?";
            int[] ints = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
                @Override
                public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
                    preparedStatement.setInt(1, Integer.valueOf(ids[i]));
                }
                @Override
                public int getBatchSize() {
                    return ids.length;
                }
            });
            System.out.println(Arrays.toString(ints));
            return ints.length;
        }
    

    二、优化新增
    1、如何选择客户类型
    给 a 标签加事件
    第一步获取a标签的文本内容即客户类型,将文本内容替换掉按钮上的内容,给隐藏的input输入框赋值

    // obj 指的就是 a标签这个对象
            function selectLevel(obj){
               // obj 指的是js 对象
               var levelName= $(obj).text();
               $("#levelBtn").html(levelName+"<span class='caret'></span>");
               $("[name='levelName']").val(levelName);
    
            }
    
         表单提交,只提交input输入框的内容,button上的文本内容是提交不了的,输入框不管隐藏或者不隐藏,都可以提交。<br /><**input type="hidden" class="form-control" id="inputPassword3" name="levelName" placeholder="客户类型"**><br />2、验证表单的数据<br />       在提交表单的时候,添加一个onclick事件,如果该函数返回false,可以阻止事件冒泡。<br />       一个摁钮,先执行onclick 事件,随即还会执行commit事件,我们为了不让它执行下一个commit事件,我们需要在onclick的时候给其返回false.
    

    三、改造当前的项目(会用就可以)
    思考:每写一个功能,就要写一个Servlet,真做一个大型的应用,岂不是要写一堆的Servlet ?
    http://localhost:8080/HqComming/customer/add
    可以截取到方法名,通过反射调用这个类中的方法即可

    public class BaseServlet extends HttpServlet {
    
        // http://localhost:8080/HqComming/customer/add
        @Override
        protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //将来所有的子servlet,会先执行BaseSerlvet中的service
            String requestURI = req.getRequestURI();// customer/add
            System.out.println(requestURI);
            int loc = requestURI.lastIndexOf("/");
            // 获取到要执行的方法名
            String methodName = requestURI.substring(loc + 1);
    
            Class<? extends BaseServlet> clazz =this.getClass();//获取到当前正在执行的类的class对象
            try {
                Method method = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
                method.invoke(this,req,resp);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    将来所有的Servlet都继承自BaseServlet即可

    package com.qfedu.servlet;
    
    import com.qfedu.pojo.Customer;
    import com.qfedu.service.CustomerService;
    import com.qfedu.service.impl.CustomerServiceImpl;
    import org.apache.commons.beanutils.BeanUtils;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.util.List;
    import java.util.Map;
    
    //http://localhost:8080/HqComming/customer/add
    @WebServlet("/customer/*")
    public class CustomerPlusServlet extends BaseServlet {
    
        CustomerService customerSerivce =new CustomerServiceImpl();
    
        public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            System.out.println("新增目前走的是最新的方法....");
            /**
             * Servlet
             * 1、获取页面数据
             * 2、给页面返回数据
             * 3、跳转页面
             */
            req.setCharacterEncoding("utf-8");
            Map<String, String[]> parameterMap = req.getParameterMap();
            Customer customer = new Customer();
            try {
                //将map中的数据,一一赋值给customer对象
                /*
                    1、必须有一个空参构造
                    2、页面上的name值必须跟实体中的属性名保持一致
                 */
                BeanUtils.populate(customer,parameterMap);
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            //进行数据的保存
            int result = customerSerivce.save(customer);
    
            if(result>0){
                resp.sendRedirect(req.getContextPath()+"/customer/show");
            }
        }
    
    
        public void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            String id = req.getParameter("id");
            int result = customerSerivce.deleteCustomerById(id);
            if(result>0){
                resp.sendRedirect(req.getContextPath()+"/customer/show");
            }
        }
    
        public void batchDel(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            //我们需要获取到页面传递过来的所有的id
            String[] ids = req.getParameterValues("ids");
    
            int result = customerSerivce.batchDel(ids);
            if (result > 0) {
                resp.sendRedirect(req.getContextPath() + "/customer/show");
            }
        }
    
    
        public void show(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            List<Customer> list = customerSerivce.showList();
            req.setAttribute("customerList",list);
            // 跳转页面到showCustomer.jsp中,然后展示出来
            //String contextPath = req.getContextPath();//获取虚拟路径名
            req.getRequestDispatcher("/showCustomer.jsp").forward(req,resp);
        }
    
    
    }
    

    此时我们的uri 从之前的一层请求变为两层请求,所以对页面的css,js有影响,每个css/js 都加上虚拟路径名
    防止加载失败。

    <script src="${pageContext.request.contextPath}/js/jquery-3.2.1.min.js" ></script>
    

    四、编辑
    1、点击编辑按钮—>去数据库查询出来该信息—>展示在编辑页面
    我们先将数据存放到req域中,然后页面通过el表达式获取req中的数据,一定要在页面上编写一个隐藏的id文本框,为后面的保存做准备。

    <input type=”hidden” value=”${cus.id}” name=”id”/>

    展示数据的时候,客户类型是页面一加载就会出现的,所以我们要在$(function(){}) 将数据修改一下

    $(function(){
                // 页面一加载 就在类型下拉框展示数据库中的会员类型
                $("#levelBtn").html("${cus.levelName}<span class='caret'></span>");
     });
    

    2、在页面上修改需要改动的数据,然后点击“保存”按钮,修改数据库中的数据
    通过传递过去的id,修改数据。

    五、查询
    准备页面端
    准备一个form表单

    <form class="form-inline" action="${pageContext.request.contextPath}/customer/search" method="post">
                    <div class="form-group">
    
                        <input type="text" name="address" class="form-control" id="exampleInputEmail3" placeholder="客户邮箱">
                    </div>
                    <!-- Single button -->
                    <div class="btn-group">
                        <button id="levelBtn" type="button" class="btn btn-success dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                            --客户类型-- <span class="caret"></span>
                        </button>
                        <ul class="dropdown-menu">
                            <li><a href="#" onclick="choiceLevel(this)">试用客户</a></li>
                            <li><a href="#" onclick="choiceLevel(this)">月卡用户</a></li>
                            <li><a href="#" onclick="choiceLevel(this)">年卡用户</a></li>
                        </ul>
                        <input type="hidden" name="levelName" />
                    </div>
    
                    <button type="submit" class="btn btn-info">查询</button>
                </form>
    

    一定要注意,选择下拉的时候一定要有一个隐藏的文本输入框。
    接着要注意SQL的拼接:因为我们的用户有可能一个条件都不输入,也有可能输入一个或多个条件,要求sql比较的灵活

            String sql = "select * from customer where 1=1 ";
            String email = customer.getAddress();
            String levelName= customer.getLevelName();
            // 用户的查询,因为我们不知道用户会选择哪些进行查询,所以sql语句不固定
            if(email!=null && !email.equals("")){
                sql += " and email like '%"+email+"%'";
            }
            if(levelName!=null && !levelName.equals("")){
                sql += " and level='"+levelName+"'";
            }
            System.out.println(sql);
    

    将来还有修改 的,未完待续。

    六、新增和修改的过期时间问题
    一个日期如何新增一周,一月,一年

    // 在此处给customer一个过期时间
            Calendar calendar = Calendar.getInstance();
            switch(customer.getLevelName()){
                case "试用客户":
                    // 过期时间=当前时间+一周
                    calendar.add(Calendar.WEEK_OF_MONTH,1);
                    break;
                case "月卡用户":
                    // 过期时间=当前时间+一月
                    calendar.add(Calendar.MONTH,1);
                    break;
                case "年卡用户":
                    // 过期时间=当前时间+一年
                    calendar.add(Calendar.YEAR,1);
                    break;
            }
            System.out.println(calendar.getTime());
            customer.setOverTime(calendar.getTime());
            return customerDao.insert(customer);
    

    修改:
    不能通过修改用户的客户类型,调整过期时间。
    可以通过修改过期时间,调整用户的过期时间。
    req.getParameterMap();
    获取到的数据都是String类型
    但是我们使用了BeanUtils.populte方法。
    map中数据向customer中的数据进行设置值。
    Customer中的overTime 是Date类型的,req中获取的overTime是String类型的
    就会报错?
    BeanUtils.populate(customer,parameterMap);
    设置值得原理是:从req的map集合中,获取值,调用customer中同名的属性的set方法。

    页面中:
    <input type=”datetime” name=”overTimeStr” class=”form-control” id=”inputPassword3” placeholder=”过期时间” value=”${cus.overTime}”>

    将来会调用customer中的overTimeStr 属性的set方法。

    public void setOverTimeStr(String overTime) throws ParseException {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            this.overTime = simpleDateFormat.parse(overTime);
     }