内容介绍
案例1:删除所选联系人
案例2:条件查询
案例3:分页查询
案例一 删除多个所选联系人
需求
在list.jsp上为每一个联系人添加一个复选框,在页面上添加一个"删除选中"按钮
然后勾选需要删除的联系人,点击按钮,删除选中联系人
思路
先在页面上添加上
技术分析
前台实现
js方式提交表单:
复选框的全选和全不选
1 delete.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap模板</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
<!-- 1.自己写的代码 -->
<script>
onload=function(){
document.getElementById("ckbox").onclick=function(){
// 获取最上面复选框的ckecked属性
var value=this.checked;
// 获取下面所有的复选框
var arr=document.getElementsByName("ck");
for(var i=0;i<arr.length;i++){
arr[i].checked=value;
}
}
}
</script>
</head>
<body>
<div class="container">
<h3 style="text-align: center">显示所有联系人</h3>
<table border="1" class="table table-bordered table-hover">
<tr>
<td colspan="9">
<form action="/day05/find" method="post">
人员名称:<input type="text" name="name" value="${name}"/>
人员QQ:<input type="text" name="qq" value="${qq}"/>
<input type="submit" value="搜索"/>
</form>
</td>
</tr>
<tr class="success">
<th> <!-- 2.自己写的代码 -->
<input type="checkbox" id="ckbox" />
</th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<!-- 5.将其转换为form表单,form表单提交,复选框内容提交,其他不提交 -->
<!-- 7.将表单提交给servlet (/day05/delete) 方式为post -->
<form action="/day05/delete" method="post" id="formId">
<c:if test="${not empty list}">
<c:forEach items="${list}" var="contact">
<tr>
<td> <!-- 3.自己写的代码 -->
<!-- 4.复选框选中就相当于 将name=value传递给后台 -->
<input type="checkbox" name="ck" value="${contact.id}"/> <%--5个复选框--%>
</td>
<td>${contact.id}</td>
<td>${contact.name}</td>
<td>${contact.sex}</td>
<td>${contact.age}</td>
<td>${contact.address}</td>
<td>${contact.qq}</td>
<td>${contact.email}</td>
<td>
<a class="btn btn-default btn-sm" href="#">修改</a>
<a class="btn btn-default btn-sm" href="#">删除</a>
</td>
</tr>
</c:forEach>
</c:if>
<tr>
<td colspan="9" align="center">
<!-- 6 将超链接改写成按钮提交 -->
<input type="button" class="btn btn-primary" value="删除选中" id="bt"></input>
</td>
</tr>
</form>
<script>
document.getElementById("bt").onclick=function(){
var flg=window.confirm("确认要删除所选用户吗?");
if(flg){
// 让表单提交
var form=document.getElementById("formId");
form.submit();
}
}
</script>
</table>
</div>
</body>
</html>
2 delete.servlet
public class DeleteServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 接受选中的id
String[] ids = request.getParameterValues("ck");
// 带着获取到的ids调用service
DeleteService deleteService = new DeleteService();
deleteService.delete(ids);
// 展示最新删除后的数据 让浏览器访问show 此处用重定向比请求转发好
// 因为可以访问项目外的其他展示页面,而请求转发只能是本项目类
response.sendRedirect("/day05/show"); //重定向
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
3 deleteService
public class DeleteService {
public void delete(String[] ids) {
DeleteDao deleteDao = new DeleteDao();
Connection con=null;
try {
DataSource dataSource = JDBCUtils.getDataSource();
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
TransactionSynchronizationManager.initSynchronization();
con= DataSourceUtils.getConnection(dataSource);
// 开启事务(将自动提交变成手动提交)
con.setAutoCommit(false);
for (String id:ids){
deleteDao.delete(jdbcTemplate,id);
}
// 手动提交
con.commit();
}catch (Exception e){
// 回滚
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally {
TransactionSynchronizationManager.clearSynchronization();
try {
con.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- deleteDao
public class DeleteDao {
public void delete(JdbcTemplate jdbcTemplate, String id) {
String sql="delete from contact where id=?";
jdbcTemplate.update(sql,id);
}
}
后台实现
将点中的用户的id传递给后台,后台根据传递的id去数据库进行删除
问题1:页面的数据如何传递给servlet?
1 超连接 <a href="servlet?username=xxx&password=xx&id=xxx">
2 表单提交 表单只要提交 表单中的input标签的内容就会以 name=value的形式进行传递
案例二 根据条件做联系人的查询(检索查询 银行必用 )
需求
在页面上添加两个文本框,人员名称和人员QQ,再添加一个查询按钮,
点击查询按钮,去数据库中查询满足条件的人员信息,然后将查询的数据显示在展示页面上
技术分析
条件查询语句
1 如果人员名称和人员qq都没填 是全部查询数据展示
2 如果人员名称填了人员qq没填 是按照人员名称查询数据展示
3 如果人员qq填了人员名称没填 是按照人员qq查询数据展示
4 如果人员名称和人员qq都填了 是既按照人员名称也按照人员qq查询数据展示
重点关注dao:
IF(NAME==""&&qq==""){
SQL=SELECT * FROM contact;
}ELSE IF(NAME!="" && qq==""){
SQL=SELECT * FROM contact WHERE NAME LIKE ?;
}ELSE IF(NAME=="" && qq!="")
{
SQL=SELECT * FROM contact WHERE qq LIKE ?;
}ELSE{
SQL=SELECT * FROM contact WHERE qq LIKE ? AND NAME LIKE ?;
}
LIST<Contact>==list.jsp
此种方式虽然逻辑很好,但是过于麻烦,不推荐
企业开发如何去优化该方式的语法呢:sql语句的拼接
1 list.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap模板</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
<script>
onload=function(){
document.getElementById("ckbox").onclick=function(){
// 获取最上面复选框的ckecked属性
var value=this.checked;
// 获取下面所有的复选框
var arr=document.getElementsByName("ck");
for(var i=0;i<arr.length;i++){
arr[i].checked=value;
}
}
}
</script>
</head>
<body>
<div class="container">
<h3 style="text-align: center">显示所有联系人</h3>
<table border="1" class="table table-bordered table-hover">
<tr> <!-- 1. 添加搜索框 -->
<td colspan="9">
<form action="/day05/find" method="post">
人员名称:<input type="text" name="name" value="${name}"/>
人员QQ:<input type="text" name="qq" value="${qq}"/>
<input type="submit" value="搜索"/>
</form>
</td>
</tr>
<tr class="success">
<th>
<input type="checkbox" id="ckbox" />
</th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<form action="/day05/delete" method="post" id="formId">
<c:if test="${not empty list}">
<c:forEach items="${list}" var="contact">
<tr>
<td>
<input type="checkbox" name="ck" value="${contact.id}"/> <%--5个复选框--%>
</td>
<td>${contact.id}</td>
<td>${contact.name}</td>
<td>${contact.sex}</td>
<td>${contact.age}</td>
<td>${contact.address}</td>
<td>${contact.qq}</td>
<td>${contact.email}</td>
<td>
<a class="btn btn-default btn-sm" href="#">修改</a>
<a class="btn btn-default btn-sm" href="#">删除</a>
</td>
</tr>
</c:forEach>
</c:if>
<tr>
<td colspan="9" align="center">
<input type="button" class="btn btn-primary" value="删除选中" id="bt"></input>
</td>
</tr>
</form>
<script>
document.getElementById("bt").onclick=function(){
var flg=window.confirm("确认要删除所选用户吗?");
if(flg){
// 让表单提交
var form=document.getElementById("formId");
form.submit();
}
}
</script>
</table>
</div>
</body>
</html>
2 findServlet
public class FindServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理中文乱码
request.setCharacterEncoding("utf-8");
// 获取人员name和qq
String name = request.getParameter("name");
String qq = request.getParameter("qq");
// 调用service
FindService findService = new FindService();
List<Contact> list = findService.find(name, qq);
// 存入到域中 带到jsp页面展示
request.setAttribute("list",list);
request.setAttribute("name",name);
request.setAttribute("qq",qq);
request.getRequestDispatcher("/list.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
3 FindService
public class FindService {
public List<Contact> find(String name, String qq) {
FindDao findDao = new FindDao();
return findDao.find(name,qq);
}
}
4 FindDao
//关注点
public class FindDao {
public List<Contact> find(String name, String qq) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
String sql="select * from contact where 666=666";
List<String> list = new ArrayList<>(); //没有
if(name.trim().length()>0){
sql=sql+" and name like ?";
list.add("%"+name+"%"); //%张%
}
if(qq.trim().length()>0){
sql=sql+" and qq like ?";
list.add("%"+qq+"%"); // %7%
}
// select * from contact where 666=666 全查
// select * from contact where 666=666 and name like ? 按照name查询
// select * from contact where 666=666 and qq like ? 按照qq查询
// select * from contact where 666=666 and name like ? and qq like ? 按照name,qq查询
Object[] obj=list.toArray();
List<Contact> list2 = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Contact.class), obj);
return list2;
}
}
搜索条件框的 数据回显:
需求:当搜索框中输入空格时,全查
案例三 分页展示数据
需求
若联系人比较多的时候,在展示页面上显示的数据特别多,导致页面特别长.
为了给用户更好的体验我们需要进行分页显示联系人信息.
6条数据:每页显示2条 一共3页
技术分析:分页
分页的作用:为了给用户更好的阅读体验
分页的分类:物理分页 逻辑分页
物理分页:企业
特点:每次点击下一页,每次就去数据库里面查询当前页的数据
优点:能够保证数据都是最新的
缺点:频繁的和数据库进行交互会带来效率低下的问题 (redis)
逻辑分页:
特点:一次性将数据全部查询出来,放在一个容器中
当每次点击下一页,不是去数据库获取,而是去容器中获取
优点:不会频繁的和数据库进行交互
缺点:不能保证数据的时时更新
Mysql提供的分页关键字:limit
格式:select * from 表 limit a,b
a:起始数据 从哪开始
b:查多少条数据
例如:每页显示2条记录第一页: select * from contact limit 0,2;
每页显示2条记录第二页: select * from contact limit 2,2;
每页显示2条记录第三页: select * from contact limit 4,2;
每页显示2条记录第四页: select * from contact limit 6,2;
每页显示2条记录第五页: select * from contact limit 8,2;
格式:select * from 表 limit 起始数据,要查的条数(每页显示的条数)
每页显示的条数固定:2条
起始数据:不固定
起始数据的规律(记住):(当前页-1)*每页显示的条数
1 0
2 2
3 4
4 6
5 8
6 10
分页上集
终极目标:将当前页的2条数据查询出来展示
页面上要展示的数据(list)
List=Select * from 表 limit ?,?;
参数(2个): 第一个?表示起始数据 第二个?表示每页显示的条数
1 需要当前页(pageNumber)
因为根据当前页可以算出起始数据 (pageNumber-1)*pageSize
2 每页显示的条数(pageSize)
固定
入口:第一页
分页下集
需要在页面定义【首页】 【上一页】 【下一页】 【尾页】
三个参数:
当前页 pageNumber 传多少代表多少
总条数 totalCount
select count(*) from contact;
总页数 totalPage 10/2=5 11/2=5+1
if(totalCount%pageSize==0){
totalPage=totalCount/pageSize
} else{
totalPage=totalCount/pageSize+1
}
1 pagelist.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>Bootstrap模板</title>
<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
<script>
onload=function(){
document.getElementById("ckbox").onclick=function(){
// 获取最上面复选框的ckecked属性
var value=this.checked;
// 获取下面所有的复选框
var arr=document.getElementsByName("ck");
for(var i=0;i<arr.length;i++){
arr[i].checked=value;
}
}
}
</script>
</head>
<body>
<div class="container">
<h3 style="text-align: center">显示所有联系人</h3>
<table border="1" class="table table-bordered table-hover">
<tr>
<td colspan="9">
<form action="/day05/find" method="post">
人员名称:<input type="text" name="name" value="${name}"/>
人员QQ:<input type="text" name="qq" value="${qq}"/>
<input type="submit" value="搜索"/>
</form>
</td>
</tr>
<tr class="success">
<th>
<input type="checkbox" id="ckbox" />
</th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<form action="/day05/delete" method="post" id="formId">
<c:if test="${not empty pb.list}">
<c:forEach items="${pb.list}" var="contact">
<tr>
<td>
<input type="checkbox" name="ck" value="${contact.id}"/> <%--5个复选框--%>
</td>
<td>${contact.id}</td>
<td>${contact.name}</td>
<td>${contact.sex}</td>
<td>${contact.age}</td>
<td>${contact.address}</td>
<td>${contact.qq}</td>
<td>${contact.email}</td>
<td>
<a class="btn btn-default btn-sm" href="#">修改</a>
<a class="btn btn-default btn-sm" href="#">删除</a>
</td>
</tr>
</c:forEach>
</c:if>
<tr>
<td colspan="9" align="center">
<input type="button" class="btn btn-primary" value="删除选中" id="bt"></input>
</td>
</tr>
</form>
<script>
document.getElementById("bt").onclick=function(){
var flg=window.confirm("确认要删除所选用户吗?");
if(flg){
// 让表单提交
var form=document.getElementById("formId");
form.submit();
}
}
</script>
<tr>
<td colspan="9" align="center">
<c:if test="${pb.pageNumber!=1}">
<a href="/day05/pageshow?pageNumber=1">【首页】</a>
<a href="/day05/pageshow?pageNumber=${pb.pageNumber-1}">【上一页】</a>
</c:if>
<%--显示页码--%>
<c:forEach begin="1" end="${pb.totalPage}" step="1" var="page">
<c:if test="${pb.pageNumber!=page}">
<a href="/day05/pageshow?pageNumber=${page}">${page}</a>
</c:if>
<c:if test="${pb.pageNumber==page}">
${page}
</c:if>
</c:forEach>
<c:if test="${pb.pageNumber!=pb.totalPage}">
<a href="/day05/pageshow?pageNumber=${pb.pageNumber+1}">【下一页】</a>
<a href="/day05/pageshow?pageNumber=${pb.totalPage}">【尾页】</a>
</c:if>
当前第${pb.pageNumber}页/一共${pb.totalPage}页 一共${pb.totalCount}条数据
</td>
</tr>
</table>
</div>
</body>
</html>
2 PageShowServlet
public class PageShowServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取当前页
int pageNumber =Integer.parseInt(request.getParameter("pageNumber")); //1 2 3
// 固定每页要展示的条数 2
int pageSize=2; //2 2 2
// 调用service
PageShowService pageShowService = new PageShowService();
PageBean pb = pageShowService.pageShow(pageNumber, pageSize);//1-2 2-2 3-2
//放入域中 带到jsp页面展示当前页的2条数据
request.setAttribute("pb",pb);
request.getRequestDispatcher("/pagelist.jsp").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request,response);
}
}
3 PageShowService
public class PageShowService {
public PageBean pageShow(int pageNumber, int pageSize) {
PageShowDao pageShowDao = new PageShowDao();
// 根据当前页计算出起始数据
int start=(pageNumber-1)*pageSize; //0 2 4
// 页面要展示的数据
List<Contact> list = pageShowDao.pageShow(start, pageSize);//0-2 2-2 4-2
// 当前页 pageNumber
// 总条数 totalCount
int totalCount=pageShowDao.findCount();
// 总页数 totalPage
int totalPage=0;
if(totalCount%pageSize==0){
totalPage=totalCount/pageSize;
}else{
totalPage=totalCount/pageSize+1;
}
// 页面:当前页要展示逇数据(list) 当前页(pageNumber) 总页数(totalPage) 总条数(totalCount)
// 对象封装一切(pageBean)
PageBean pb = new PageBean();
pb.setList(list);
pb.setPageNumber(pageNumber);
pb.setPageSize(pageSize);
pb.setTotalCount(totalCount);
pb.setTotalPage(totalPage);
return pb;
}
}
4 PageShowDao
public class PageShowDao {
public List<Contact> pageShow(int start, int pageSize) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
String sql="select * from contact limit ?,?";
List<Contact> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Contact.class), start, pageSize);
return list;
}
public int findCount() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(JDBCUtils.getDataSource());
String sql="select count(*) from contact";
int count = jdbcTemplate.queryForObject(sql, int.class);
return count;
}
}