Ajax技术已经不算什么新鲜事了,Ajax局部刷新的文章在网上已经应有尽有,但是,这些文章有一个很严重的缺点,就是把查询出来的内容在JS不停地构造HTML内容,再把这些内容放在页面,好像自己的JS构造节点技术很牛B很熟练似的,或者认为查询出来的内容只能通过这种方法去局部刷新。导致后期大部分HTML在JavaScript脚本里面,IDE工具无法识别。现在不说Javascript熟练不熟练的问题。主要是脚本就应该是脚本,HTML就应该是HTML,混在一起根本就画面太丑没法看。一方面用框架不停地声称耦合度什么的,一方面自己就写出一堆耦合度极其恐怖的程序,根本不知道是什么心态。那么,如果把Ajax查询出来的内容放在HTML显示,尽量避免利用Javascript构造节点呢?你或许需要JQuery的load方法。下面用一个Servlet3.0的例子来说明这个东西,免得SSH杂糅太多包让人看不懂。
一、基本目标
修改数据库的表单在1.jsp,
2.jsp只是用来显示数据库的查询信息。也就是说2.jsp这是那张表格。
修改数据之后,我们只需要局部刷新2.jsp是不是?这样没这么卡是不是?
二、基本思想
Web工程的目录结构如下,ajax技术必须要jQuery,然后,Servlet3.0中必须的javax.servlet-api-3.1.0.jar,查询MySql必须的mysql-connector-java-5.1.32.jar就不说了。网上自己一搜就有了。web.xml除了jsp的基本框架以外,不用写任何东西,让Eclipse自动创建就行了《【Javaweb】Eclipse for JavaEE新建的Web工程自动生成web.xml》(点击打开链接),随后,所有Servlet直接用Servlet3.0标准配置。
然后,整个网络工程的大体流程是这样的。可能有点乱,但是配合下面的代码,应该大致能够理解的。
三、制作过程
1、首先dbDAO.java如下,这个文件在《【Servlet】根据MVC思想设计用户登陆、用户注册、修改密码系统》(点击打开链接)已经讲解过了,这里就不讲了。完全一模一样,一个字都没有改
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(); } } }
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <%@ page import="java.util.*"%> <!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"> <script src="jquery-1.11.1.js"></script> <title>2</title> </head> <body> <table border="1" id="data"></table> </body> </html> <script> $.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>
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(); } }
首先是HTML布局如下,当然,里面有很多无关紧要的文本,主要是用来说明这些文本到头来是不会刷新的。
loadHTML是用来载入2.jsp的。相当于以前很流行,但现在被人唾弃的iframe。还有一个等待脚本载入的下来列表。
<%@ 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>1</title> <script src="jquery-1.11.1.js"></script> </head> <body> 我是1.jsp的内容! <p style="color: blue">我是不被刷新的</p> <span style="color: red">我是不被刷新的</span> <br /> id= <select id="id"></select> username= <input type="text" id="username" name="username" /> number= <input type="text" id="number" name="number" /> <button onclick="ajaxSubmit()">修改</button> <h1>==============以下为2.jsp的内容!====================</h1> <div id="loadHTML"></div> <h1>==============以上为2.jsp的内容!====================</h1> 我是1.jsp的内容! <br /> <p style="color: blue">我是不被刷新的</p> <span style="color: red">我是不被刷新的</span> </body> </html>这个页面的脚本如下,一上来就通过load方法载入2.jsp的内容,也就是读取数据库里面的东西。然后,通过countDataBase.java这个Servlet,载入当前testtable的id列。之后,为修改按钮提供脚本,传递表达的数据什么id,username,number等给update.java这个Servlet根据此来修改数据。
<script> $("#loadHTML").load("2.jsp"); $.ajax({ type : "post", url : "countDataBase", dataType : "text", success : function(data) { data = eval(data); for (var i = 0; i < data.length; i++) { option = document.createElement("option"); option.innerHTML = data[i].id; option.value = data[i].id; document.getElementById("id").appendChild(option); } }, error : function() { alert("出错了"); } }); function ajaxSubmit() { var id = $("#id").val(); var username = $("#username").val(); var number = $("#number").val(); $.ajax({ type : "post", url : "update", data : { id : id, username : username, number : number, }, success : function(data) { $("#loadHTML").load("2.jsp"); }, error : function() { alert("出错了"); } }); } </script>
import java.io.*; import java.sql.ResultSet; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; @SuppressWarnings("serial") @WebServlet(name = "countDataBase", urlPatterns = { "/countDataBase" }) public class countDataBase extends HttpServlet { 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("},"); } } 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(); } }
import java.io.*; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.annotation.*; @SuppressWarnings("serial") @WebServlet(name = "update", urlPatterns = { "/update" }) public class update extends HttpServlet { 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 { request.setCharacterEncoding("utf-8"); String id=(String)request.getParameter("id"); String username=(String)request.getParameter("username"); String number=(String)request.getParameter("number"); try { dbDAO db = new dbDAO(); db.modify("update testtable set username=? where id=?",username,id); db.modify("update testtable set number=? where id=?",number,id); } catch (Exception e) { e.printStackTrace(); } PrintStream out = new PrintStream(response.getOutputStream()); response.setContentType("text/html;charSet=utf-8"); //搞完把json打印在本Servlet上,之后前台页面读这页的内容就可以了 out.println("修改成功"); out.close(); } }
大家可以看到1.jsp中的脚本中根本没有过多的html代码,数据库查询出来的东西,只需要在2.jsp进行简单的构造就可以,利用一个简单的load方法,把2.jsp读进来。不要直接在1.jsp的脚本中构建一个表格。这达到了html代码与javascript的代码分离的目的,同时每一次修改只是刷新一个div的内容,到达了局部刷新的效果。以后要修改数据库查询的内容。比如2.jsp中的那个表格的样式,你就不用再脚本中修改。直接该2.jsp集合。2.jsp的作用不是正如以前iframe时代那些banner.html,footer.html……吗?而1.jsp不是正是如同以前充满iframe标签的主页面吗?