一、基本思想

首先明确一点,在web中的request、session、application的三大容器中是不能存放arraylist<Class>类动态数组的,这些容器实质上只是一个存放Object的HashMap,你把HashMap的东西根据key取出来之后,其值根本无法如同String,int通过强制数组转换成arraylist<Class>类动态数组的,即使可以也是非常麻烦的。这些东西都是Java的基本数据结果,具体可以参见《【Java】Java中的Collections类——Java中升级版的数据结构》(点击打开链接)。当然还有一个,但page容器已经可以用脚本代替了,这里就不说了。因此问题就来了,用数据库查出来的表怎么传到前台?这里不像php能够直接输出,也不想aspx有一个数据适配器,还有一个数据源这么爽。所以三大框架就这样应运而生呢?当然,在普普通通的Servlet中,你还是利用json+ajax把整张从数据库查出的表推向前台。

JSON其实也不是什么玄虚的东西,它只是一个通用于前台后台的Map,通过key能够轻松value的东西,而且本质只是一个字符串。

例如var jsonExample={"id":"1","s":"23333"}就是一个Json,你通过jsonExample.id就等到一个1了,jsonExample.s就是23333了。吐舌头


二、基本目标

下面举个例子说明在普普通通的Servlet中,如何利用json+ajax把数据库查询出来的表推向前台显示。


在网页中点击查询,马上输入一张test数据库的testtable表,

可以看到,每次点击查询,实际上从后台推来一个由JSON构成的数组。


三、制作思想

1、首先在Eclipse for javaee中搭好Servlet与JDBC的开发环境,也就是在WEB-INF\lib目录中放入网上一搜就有的javax.servlet-api-3.1.0.jar与mysql-connector-java-5.1.32.jar。web.xml里面什么都不用写,一会儿按照Servlet3.0标准去构建,按照Eclipse for javaee自动生成的就可以了,具体见《【Javaweb】Eclipse for JavaEE新建的Web工程自动生成web.xml》(点击打开链接)。在WebContent放入Jquery支持Ajax。在src写好Servlet的Model,具体见《【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统》(点击打开链接),跟里面的dbDAO.java一模一样,具体如下:

import java.sql.*;

public class dbDAO {
	private Connection con;

	// 构造函数,连接数据库
	public dbDAO() throws Exception {
		String dburl = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useOldAliasMetadataBehavior=true";
		String dbusername = "root";
		String dbpassword = "root";
		Class.forName("com.mysql.jdbc.Driver");
		this.con = DriverManager.getConnection(dburl, dbusername, dbpassword);
	}

	// 执行查询
	public ResultSet query(String sql, Object... args) throws Exception {
		PreparedStatement ps = con.prepareStatement(sql);
		for (int i = 0; i < args.length; i++) {
			ps.setObject(i + 1, args[i]);
		}
		return ps.executeQuery();
	}

	// 执行插入
	public boolean insert(String sql, Object... args) throws Exception {
		PreparedStatement ps = con.prepareStatement(sql);
		for (int i = 0; i < args.length; i++) {
			ps.setObject(i + 1, args[i]);
		}
		if (ps.executeUpdate() != 1) {
			return false;
		}
		return true;
	}

	// 执行修改
	public boolean modify(String sql, Object... args) throws Exception {
		PreparedStatement ps = con.prepareStatement(sql);
		for (int i = 0; i < args.length; i++) {
			ps.setObject(i + 1, args[i]);
		}
		if (ps.executeUpdate() != 1) {
			return false;
		}
		return true;
	}

	// 析构函数,中断数据库的连接
	protected void finalize() throws Exception {
		if (!con.isClosed() || con != null) {
			con.close();
		}
	}
}

一切搞好,整个Web工程的目录结构如下。关键是index.jsp请求ServletJson.java去查询数据库,然后ServletJson.java营造一个Json字符串推回给index.jsp。index.jsp再于自己的脚本中构建相应的节点显示到网页中。


2、先说ServletJson.java,由于dbDAO.java的存在,直接通过调用里面的query方法送条sql语句给它就可以查询了。然后通过循环构造一个JSON数组给index.jsp的javascript。Javascript中,无论是什么数组,都应该用[]表示。然后JSON就是诸如{"id":"1","s":"23333"}的东西,注意的是,key与value都要被双引号引着。无论value是数还是字符串,都要有双引号。没有双引号会出错的!在Servlet中利用输出流打印出一个Json字符串就行了,无需用到网上那些包,自己构造出Json就可以了。注意格式。

import java.io.*;
import java.sql.*;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

//说明这个Servlet是没有序列号的
@SuppressWarnings("serial")
//说明这个Servlet的名称是jsonRequest,其地址是/jsonRequest这与在web.xml中设置是一样的
@WebServlet(name = "jsonRequest", urlPatterns = { "/jsonRequest" })
public class ServletJson extends HttpServlet {
	//放置用户之间通过直接在浏览器输入地址访问这个servlet
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		PrintStream out = new PrintStream(response.getOutputStream());
		response.setContentType("text/html;charSet=utf-8");
		out.print("请正常打开此页");
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		//把从数据库的查询结果构造一个json字符串推向前台
		StringBuffer json = new StringBuffer();
		json.append("[");
		try {
			dbDAO db = new dbDAO();
			ResultSet rs = db.query("select * from testtable");
			while (rs.next()) {
				json.append('{');
				//注意每一个key-value对都要在引号之中,单引号或者双引号都可以
				json.append("'id':").append("'").append(rs.getInt("id")).append("'").append(",");
				json.append("'username':").append("'")
						.append(rs.getString("username").trim()).append("'").append(",");
				json.append("'number':").append("'")
						.append(rs.getString("number").trim()).append("'");
				json.append("},");
			}			

		} catch (Exception e) {
			e.printStackTrace();
		}
		//这是为了删除最后一次循环中出现的那个逗号
		json.deleteCharAt(json.length() - 1);
		json.append("]");
		PrintStream out = new PrintStream(response.getOutputStream());
		response.setContentType("text/html;charSet=utf-8");
		//搞完把json打印在本Servlet上,之后前台页面读这页的内容就可以了
		out.println(json.toString());
		out.close();
	}
}

3、index.jsp

这一页主要对返回Json的字符串进行解析,注意,请求的类型是text,再用eval去把它换成json就可以了,请求类型是json是不行的,因为传过来的东西是json数组,数组,而不是json。构造的时候利用文件碎片,不懂请看《【JavaScript】利用文件碎片DocumentFragment改进兼容IE6可调可控的图片滑块》(点击打开链接)与《【JavaScript】网页节点的增删改查》(点击打开链接)技术把查询页面呈现在页面上,这样你就不用多次把节点搬到页面上,频繁地局部更新页面是不好的,拼接的时候注意先把源table节点的东西清空。

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ServletJson</title>
<!-- 注意引入jquery -->
<script src="jquery-1.11.1.js"></script>
</head>
<body>
	<button οnclick="ajaxSubmit()">查询</button>
	<table border="1" id="data">
	</table>
</body>
</html>
<script>
	function ajaxSubmit() {
		$.ajax({
			type : "post",
			url : "jsonRequest",
			dataType : "text",
			success : function(data) {
				data = eval(data);
				//构造前先清空源节点
				document.getElementById("data").innerHTML = "";
				//设置一个文件碎片
				var frag = document.createDocumentFragment();
				//这是表头
				var tr = document.createElement("tr");
				tr.innerHTML = "<td>id</td><td>username</td><td>number</td>";
				frag.appendChild(tr);
				//利用循环构造表格的每一行,把其放在文件碎片上面
				for (var i = 0; i < data.length; i++) {
					tr = document.createElement("tr");
					tr.innerHTML = "<td>" + data[i].id + "</td>" + "<td>"
							+ data[i].username + "</td>" + "<td>"
							+ data[i].number + "</td>";
					frag.appendChild(tr);
				}
				//此时文件碎片已经是一张表了,直接放网页就可以了
				document.getElementById("data").appendChild(frag);
			},
			error : function() {
				alert("出错了");
			}

		});
	}
</script>


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐