使用纯ajax和Servlet的数据交互实现JavaWeb无刷新分页显示含模糊查询

    首先说明使用的jar包和开发工具

三个jar包
    三个jar包实现,分别是:fastjson-1.2.13.jar , jstl.jar 和 standard.jar。
    附上下载路径 https://download.csdn.net/download/hupersan/11157286
    开发工具:mysclipse 8.5、JDK1.7
    数据库:MySql5.6

    整体实现标题所述的效果除了实体类和dao包以及jsp页面仅使用了一个js和两个Servlet

    重点讲解一下实现思路

  1. 首先Page是一个封装的实体类,里面有四个参数,在这里直接上代码不做过多解释。
// 四个参数
private int currentPage; // 当前页码
private int totalCount; // 数据总条数
private int totalPage; // 总页数
private int pageSize; // 每页数据量

   对以上四个参数进行封装,下文所有涉及到Page相关的都是指这四个参数。

  1. 接下来进入正题,如果要使用无框架达到无刷新的分页效果,涉及到三个界面的数据交互,jsp,js和Servlet。首先排除jsp界面,为了达到无刷新的效果我固定了jsp的table格式,好在js页面对每一个tr里td的内容进行替换,以此来实现一个无刷新的分页效果,jsp关键部分,代码如下:
	<table class="selectTable">
		<tr>
			<th width="3%"><input type="checkbox"/></th>
			<th width="3%">商品编号</th>
			<th width="10%">商品名称</th>
			<th width="10%">商品类型</th>
			<th width="10%">商品单价</th>
			<th width="10%">商品总数量</th>
			<th width="10%">操作</th>
		</tr>
		<tr>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
		</tr>
		<tr>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
		</tr>
		<tr>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
		</tr>
		<tr>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
		</tr>
		<tr>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
			<td>&nbsp;</td>
		</tr>
	</table>
	
	<input type="button" value="首页" name="first"/>
	<input type="button" value="上一页" name="up"/>
	<span class="showPage">1/1</span> 页
	<input type="button" value="下一页" name="down"/>
	<input type="button" value="尾页" name="last"/>
	转到第<input type="text" name="number"/>页
	<input type="button" name="jump" value="跳转"/>

    在这里我设置的默认每页数据条数是5,所以就要搭五个tr。th中以百分数设置宽度,是为了固定每一个列的宽窄(所有列相加就是100%这样方便计算和使用)。

  1. 在jsp页面固定了table之后,就要在js和Servlet两者中选择一个进行页面的Page和数据内容的交互,由于Servlet属于服务器端,js属于客户端小脚本,为了减轻服务器的工作量,所以选择在js页面进行相对而言更繁重的相关数据操作。

    接下来考虑到分页显示信息的两部分变量,Page和页面显示的信息数据,于是使用了两个Servlet。

    一个PageServlet用来接收js传输过来的信息并返回Page相关信息转换后的的Json字符串,在js中进行回调。

    PageServlet,代码如下:

		
		// 得到每页显示的数据量
		Integer pageSize = Integer.valueOf(request.getParameter("pageSize"));
		String input = request.getParameter("input");// 获得用户模糊查询使用的输入内容

		//多态实体化impl
		Item_FrameDao id = new Item_FrameDaoImpl();
		// 声明总条数
		int counts;
		//对应impl中的两个sql语句
		if (input == null || input == "") {
			counts = id.sumItem_FrameDao();// 总条数
		} else {
			counts = id.sumItem_FrameDao(input);// 总条数
		}

		// 再获得总页数
		int totalPage= 1;
		if (counts % pageSize == 0) {
			totalPage= counts / pageSize;
		} else {
			totalPage = counts / pageSize + 1;
		}
		// 将数据存入实体类
		Page pa = new Page();
		pa.setTotalCount(counts);
		pa.setTotalPage(totalPage);
		
		// 将实体类转换为json串
		String json = JSON.toJSONString(pa);
		// 回调
		out.print(json);

    以上为手写的万能查询方法,c3p0同理,不做展示。

    js中的代码:

$(document).ready(function() {
		var currentPage = 1;// 当前页码
		var totalPage = 1;// 总页码
		var pageSize = 5;// 每页显示的数据量
		var pageCount = 1;// 数据库总条数
		var input="";//用户输入
		
		// 传pageSize,得到pageCount和totalPage(模糊查询传送用户输入)
		$.post("PageServlet", "pageSize=" + pageSize+"&input="+input, function(servletPage) {
			var pa = $.parseJSON(servletPage);
				totalPage = pa.totalPage;// 总页码
				pageCount = pa.totalCount;// 总条数
				showPage();// 显示页码
				pageInfo();// 直接获取数据
			});

		// 显示*/*
		function showPage() {
			if(pageCount%pageSize==0){
				currentPage=pageCount/pageSize;
			}
			//避免出现0/0的情况
			if(pageCount==0){
				totalPage=1;
			}
			//避免出现0/0的情况
			if(currentPage==0){
				currentPage=1;
			}
			//如果当前页码大于总页码,就将当前页码重新赋值为总页码
			if(currentPage>totalPage){currentPage=totalPage};
			//显示出?/?的状态
			$(".showPage").text(currentPage + "/" + totalPage);
		}

		// 获取分页数据
		function pageInfo() {
			//如果不选中table替换td内容或元素的话,就会出现问题,比如说12条数据显示完第13行不是空行,而是接着显示前面的据替换在第13行和接下来的空行的位置
			$(".selectTable tr td").html("&nbsp;");
			$.post("FenYeServlet", "currentPage="+currentPage+"&pageSize="+pageSize+"&input="+input, function(pageJson) {
					var fenYe = $.parseJSON(pageJson);
					if (fenYe == "[]") {
						return;
					}
					var num = 1;// 表格的行号
					$(fenYe).each(function() {
							//其中num代表第几行,td:eq(?)代表当前行的第几个列,html表示替换标签样式,txt表示替换文本内容
							$("tr:eq("+num+")").children("td:eq(0)").html("<input type='checkbox' class='item' value='"+this.cid+"'/>");
							$("tr:eq("+num+")").children("td:eq(1)").text((currentPage-1)*pageSize+num);//序号
							$("tr:eq("+num+")").children("td:eq(2)").text(this.cname);//商品名称
							$("tr:eq("+num+")").children("td:eq(3)").text(this.itemtype);//商品类型
							$("tr:eq("+num+")").children("td:eq(4)").text(this.num);//商品单价
							$("tr:eq("+num+")").children("td:eq(5)").text(this.price);//商品总数量
							//a标签中的href='javascript:void(0)'表示让a标签走一个空方法,指向一个死链接
							$("tr:eq("+num+")").children("td:eq(6)").html("<a href='SelectUpDateServlet?cid="+this.cid+"' class='update'>修改</a>/<a href='javascript:void(0)' class='del'>下架</a>");//操作
							num++;// 序号+1
						});//循环结束
					//这里需要为下架绑定点击事件,否则下架按钮就算设置了点击事件也不会有反应,修改跳转servlet无需绑定事件
					$(".del").on("click",function() {
						//得到checkbox的value也就是选中商品对应的数据库id
						var id = $(this).parents("tr").find(".item").val().trim();
						var isSure = confirm("您确定要下架该商品?");
						if (isSure  == false) {
							return;
						}
						delItem(id);
					})
				});
		}
		
		//下架商品的方法
		function delItem(id){
			$.post("DelItem_FrameServlet", "cid=" + id, function(data) {
				if (data == "true") {
					alert("下架成功!");
					//获得总条数和总页数,PageServlet
					$.post("PageServlet","pageSize="+pageSize+"&input="+input,function(data){
						//jQuery提供了parseJSON(),将普通文本转换为json串。
						var pa=$.parseJSON(data);
						//从数据库返回总条数和总页数
						totalCount=pa.totalCount;
						totalPage=pa.totalPage;
						if(totalCount==pageSize){
							//如果总条数等于每页显示的数据量,就触发首页的点击事件
						 	$('input[name=first]').trigger("click");//trigger中文含义“触发”
						}else if(totalCount%pageSize==0){
							//如果总条数余每页显示的数据量等等于0,就触发上一页的点击事件
							$('input[name=up]').trigger("click");
						}
						showPage();
					});
					pageInfo();//调用分页方法
				} else {
					alert("下架失败!");
				}
				});
		}
})

    上述操作中对a标签使用 href=‘javascript:void(0)’ 的含义是,让超链接去执行一个js函数,而不是去跳转到一个地址,而void(0)表示一个空的方法,也就是不执行js函数,仅仅表示一个死链接。

    另一个FenYeServlet则用来接收js传输过来的信息时并返回页面显示的数据相关信息转换后的Json字符串,在js中进行回调。

    FenYeServlet,代码如下:

	// 获得当前页码和每页显示的数据量
		Integer currentPage = Integer.valueOf(request.getParameter("currentPage"));// 当前页码
		Integer pageSize = Integer.valueOf(request.getParameter("pageSize"));// 每页显示的数据量
		String input = request.getParameter("input");// 获得用户输入

		// 得到分页信息
		Item_FrameDao if = new Item_FrameDaoImpl();
		//声明集合
		List<Item_Frame> gList= if.FenYe(input, currentPage, pageSize);

		// 转换为json串
		String json = JSON.toJSONString(gList);
		// 回调
		out.print(json);

    如果数据中含有时间类型,可以在将集合转换为json字符串向js传的时候调用JSON.toJSONStringWithDateFormat(集合,“日期格式”);将时间格式转换过来。

    以上代码中,获取数据集合的impl方法如下:

	/**
	 * 根据用户输入进行模糊查询
	 * @return
	 */
	public List<Item_Frame> FenYe(String input, int currentPage,int pageSize) {
		String sql = "select * from item_Frame where  cname like ? order by cid desc limit ?,?;";
		return BaseDao.getEntityList(sql, Item_Frame.class, "%" + input+ "%", (currentPage - 1) * pageSize,pageSize);
	}

    以上代码的返回值BaseDao部分代码如下:

	//实体类列表
	public static <T> List<T> getEntityList(String sql, Class<T> cla,Object... objects) {
		Connection con = getCon();
		PreparedStatement ps = null;
		ResultSet rs = null;
		List<T> lists = new ArrayList<T>();
		try {
			ps = con.prepareStatement(sql);
			if (objects != null) {
				for (int i = 0; i < objects.length; i++) {
					ps.setObject(i + 1, objects[i]);
				}
			}
			rs = ps.executeQuery();
			while (rs.next()) {
				T entity = cla.newInstance();
				Field[] fields = cla.getDeclaredFields();
				for (Field field : fields) {
					field.setAccessible(true);
					field.set(entity, rs.getObject(field.getName()));
				}
				lists.add(entity);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			close(con, ps, rs);
		}
		return lists;
	}

    以上为手写的返回实体类列表方法,但有一个小缺陷。比如类型转换的时候数据库是int类型,实体类的类型就必须要设成long,这是使用反射的一个缺陷,不过不影响接下来的操作,不做过多的解释。c3p0同理,不做展示。

    js中的代码:

//模糊查询点击事件
$(".moCha").click(function() {
			currentPage=1;
			input = $(".qingzaicisousuo").val().trim();
			$.post("PageServlet", "pageSize=" + pageSize+"&input="+input, function(servletPage) {
				var pa = $.parseJSON(servletPage);
					totalPage = pa.totalPage;// 总页码
					pageCount = pa.totalCount;// 总条数
					showPage();// 显示页码
				});
		pageInfo();// 直接获取数据!!!注意展示数据并没有在post里直接调用而是在外面调用
})//结束

    以上就是js的模糊查询点击事件中的分页操作,当触发点击事件时,为当前页面重新赋初始值(有必要)!接收用户的输入,传入PageServlet获取相关信息,回调并解析json串,设置总页码和总条数,调用显示页码的方法,post结束!在post外调用pageInfo()方法!否则PageServlet会报空异常,控制台会提醒是转换异常,因为空值是没办法用Integer.valueOf()方法转换的,会报转换异常但是实际错误并不在转换上,而是内部调用的方法中还包括调用其他方法就会导致空值。

    附上效果图:

商品分页效果图    还有上一页、下一页、首页、尾页、?/?和跳转的功能实现,其中显示 ?/? 的js代码在上文中有出现,这里不重复展示,直接上代码:

// “上一页”点击事件
$("input[name=up]").click(function() {
	// 当前页码-1
	if (currentPage == 1) {
		currentPage = 1;
		return;
	} else {
		currentPage--;
		showPage();// 显示页码
		pageInfo();// 直接获取数据
	}
})// 上一页结束
// “下一页”点击事件
$("input[name=down]").click(function() {
	// 当前页码+1
	if (currentPage == totalPage) {
		return;
	} else {
		currentPage++;
		showPage();// 显示页码
		pageInfo();// 直接获取数据
	}
})// 下一页结束
//“首页”点击事件
$("input[name=first]").click(function() {
	//防止首页时点击首页事件时重新替换
	if(currentPage ==1){
		return;
	}
	// 当前页码=1
	currentPage=1;
		showPage();// 显示页码
		pageInfo();// 直接获取数据
})// 首页结束
// “尾页”点击事件
$("input[name=last]").click(function() {
	//防止尾页时点击尾页事件时重新替换
	if(currentPage == totalPage){
		return;
	}
	// 当前页码=总页数
	currentPage = totalPage;
	if (currentPage > totalPage) {
		currentPage = totalPage;
		return;
	} else {
		showPage();// 显示页码
		pageInfo();// 直接获取数据
	}
})//尾页结束
//“跳转”点击事件
// 点击跳转按钮时对输入跳转页面的数字进行判断
$("input[name=jump]").click(function() {
	// 获得跳转页面框输入的数字
	var num = $("input[name=number]").val().trim();
	var pre =/^\d*$/;	//正则表达式,返回boolean类型
	if(pre.test(num)==false){
		alert("请输入正确的数字!");
		$("input[name=number]").val("");
		return;
	}
	if(num>totalPage){
		alert("不能超出当前页!");
		$("input[name=number]").val("");
		return;
	}
	if(num<1){
		alert("跳转页码不能小于1!");
		$("input[name=number]").val("");
		return;
	}
	currentPage=num;
	$(".showPage").text(currentPage + "/" + totalPage);
	pageInfo();// 直接获取数据
})// 跳转结束

    至此,使用纯ajax和Servlet的数据交互实现JavaWeb无刷新分页显示含模糊查询结束,第一次发博客,欢迎大家多提建议。

		by      琥珀酱~
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值