项目第四天—实战

一、批量删除

需要注意的点:
如何将页面上选中的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提交表单

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

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

  1. public int batchDel(String[] ids) {
  2. String sql ="delete from customer where id=?";
  3. int[] ints = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
  4. @Override
  5. public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
  6. preparedStatement.setInt(1, Integer.valueOf(ids[i]));
  7. }
  8. @Override
  9. public int getBatchSize() {
  10. return ids.length;
  11. }
  12. });
  13. System.out.println(Arrays.toString(ints));
  14. return ints.length;
  15. }

二、优化新增

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

  1. // obj 指的就是 a标签这个对象
  2. function selectLevel(obj){
  3. // obj 指的是js 对象
  4. var levelName= $(obj).text();
  5. $("#levelBtn").html(levelName+"<span class='caret'></span>");
  6. $("[name='levelName']").val(levelName);
  7. }

表单提交,只提交input输入框的内容,button上的文本内容是提交不了的,输入框不管隐藏或者不隐藏,都可以提交。
<input type=”hidden” class=”form-control” id=”inputPassword3” name=”levelName” placeholder=”客户类型”>
2、验证表单的数据
在提交表单的时候,添加一个onclick事件,如果该函数返回false,可以阻止事件冒泡。
一个摁钮,先执行onclick 事件,随即还会执行commit事件,我们为了不让它执行下一个commit事件,我们需要在onclick的时候给其返回false.

三、改造当前的项目(会用就可以)

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

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

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

  1. package com.qfedu.servlet;
  2. import com.qfedu.pojo.Customer;
  3. import com.qfedu.service.CustomerService;
  4. import com.qfedu.service.impl.CustomerServiceImpl;
  5. import org.apache.commons.beanutils.BeanUtils;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.annotation.WebServlet;
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import java.io.IOException;
  11. import java.util.List;
  12. import java.util.Map;
  13. //http://localhost:8080/HqComming/customer/add
  14. @WebServlet("/customer/*")
  15. public class CustomerPlusServlet extends BaseServlet {
  16. CustomerService customerSerivce =new CustomerServiceImpl();
  17. public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  18. System.out.println("新增目前走的是最新的方法....");
  19. /**
  20. * Servlet
  21. * 1、获取页面数据
  22. * 2、给页面返回数据
  23. * 3、跳转页面
  24. */
  25. req.setCharacterEncoding("utf-8");
  26. Map<String, String[]> parameterMap = req.getParameterMap();
  27. Customer customer = new Customer();
  28. try {
  29. //将map中的数据,一一赋值给customer对象
  30. /*
  31. 1、必须有一个空参构造
  32. 2、页面上的name值必须跟实体中的属性名保持一致
  33. */
  34. BeanUtils.populate(customer,parameterMap);
  35. } catch (Exception e) {
  36. e.printStackTrace();
  37. }
  38. //进行数据的保存
  39. int result = customerSerivce.save(customer);
  40. if(result>0){
  41. resp.sendRedirect(req.getContextPath()+"/customer/show");
  42. }
  43. }
  44. public void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  45. String id = req.getParameter("id");
  46. int result = customerSerivce.deleteCustomerById(id);
  47. if(result>0){
  48. resp.sendRedirect(req.getContextPath()+"/customer/show");
  49. }
  50. }
  51. public void batchDel(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  52. //我们需要获取到页面传递过来的所有的id
  53. String[] ids = req.getParameterValues("ids");
  54. int result = customerSerivce.batchDel(ids);
  55. if (result > 0) {
  56. resp.sendRedirect(req.getContextPath() + "/customer/show");
  57. }
  58. }
  59. public void show(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  60. List<Customer> list = customerSerivce.showList();
  61. req.setAttribute("customerList",list);
  62. // 跳转页面到showCustomer.jsp中,然后展示出来
  63. //String contextPath = req.getContextPath();//获取虚拟路径名
  64. req.getRequestDispatcher("/showCustomer.jsp").forward(req,resp);
  65. }
  66. }

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

  1. <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(){}) 将数据修改一下

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

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

五、查询

准备页面端
准备一个form表单

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

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

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

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

六、新增和修改的过期时间问题

一个日期如何新增一周,一月,一年

  1. // 在此处给customer一个过期时间
  2. Calendar calendar = Calendar.getInstance();
  3. switch(customer.getLevelName()){
  4. case "试用客户":
  5. // 过期时间=当前时间+一周
  6. calendar.add(Calendar.WEEK_OF_MONTH,1);
  7. break;
  8. case "月卡用户":
  9. // 过期时间=当前时间+一月
  10. calendar.add(Calendar.MONTH,1);
  11. break;
  12. case "年卡用户":
  13. // 过期时间=当前时间+一年
  14. calendar.add(Calendar.YEAR,1);
  15. break;
  16. }
  17. System.out.println(calendar.getTime());
  18. customer.setOverTime(calendar.getTime());
  19. 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方法。

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