项目第四天—实战
一、批量删除
需要注意的点:
如何将页面上选中的checkbox提交给servlet?
页面端: name value
<input type=”checkbox” name=”ids” value=”${cus.id}”/>
将table包裹一层form表单
<!--form表单的提交只提交input输入框内的值--><form id="form" action="${pageContext.request.contextPath}/batchDel" method="post"><table class="table table-bordered table-hover"><thead><tr><th><input type="checkbox" id="checkAll"/></th><th>序号</th><th>客户邮箱</th><th>客户登记</th><th>过期时间</th><th>编辑</th><th>删除</th></tr></thead><tbody><c:if test="${not empty customerList}"><c:forEach items="${customerList}" var="cus" varStatus="vvv"><tr><td scope="row"><input type="checkbox" name="ids" value="${cus.id}"/></td><td>${vvv.count}</td><td>${cus.address}</td><td>${cus.levelName}</td><td>${cus.overTimeStr}</td><td><a href="#"> <span class="glyphicon glyphicon-edit"></span></a></td><td><a onclick="delConfirm(${cus.id})"> <span class="glyphicon glyphicon-trash"></span></a></td></tr></c:forEach></c:if></tbody></table></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() {@Overridepublic void setValues(PreparedStatement preparedStatement, int i) throws SQLException {preparedStatement.setInt(1, Integer.valueOf(ids[i]));}@Overridepublic 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上的文本内容是提交不了的,输入框不管隐藏或者不隐藏,都可以提交。
<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
可以截取到方法名,通过反射调用这个类中的方法即可
public class BaseServlet extends HttpServlet {// http://localhost:8080/HqComming/customer/add@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//将来所有的子servlet,会先执行BaseSerlvet中的serviceString requestURI = req.getRequestURI();// customer/addSystem.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 {//我们需要获取到页面传递过来的所有的idString[] 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);}
