Ajax的关键:XMLHttpRequest对象
期望的效果如下:
有这样一个表单(类似注册)
当用户输入用户名,且User name输入框失去焦点时,立即判断该用户输入的用户名是否合法:如果用户名已经存在则给出类似下面的提示:
达到较好的用户体验。【密码输入框有空的读者自行实践,这里不做过多描述】
关键代码如下【主要用到了Servlet+jdbc】:
首先是这个“简陋”的表单:
<form action="#">
User name:<input type="text" id = "name" οnblur="checkUserName()"><label id="nameMsg"></label><br/>
PassWord:<input type="password" id = "password" οnblur="checkPassword()"><label id="passMsg"></label><br/>
<input type="submit" value="注册">
</form>
然后是js代码:
<script type="text/javascript">
function createXMLHttpRequest(){
try{
return new XMLHttpRequest();//大多数浏览器
}catch(e){
try{
return new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
return new ActiveXObject("Microsoft.XMLHTTP");
}
}
}
function checkUserName(){
var xmlHttp = createXMLHttpRequest();
var username = document.getElementById("name").value;
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState==4&&xmlHttp.status==200){
var name = document.getElementById("nameMsg");
name.innerHTML = xmlHttp.responseText;
}
};
xmlHttp.open("POST", "/AjaxDemo1/BServlet", true);
xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlHttp.send("username="+username);
}
</script>
【注】简单说明一下,post请求必须设置 content-type的请求头为xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
其实这个就是表单ectype的默认值,等同于设置了content-type请求头,不过这里我们用的是Ajax的方式发送请求,这里没有默认值,需要我们自己指定。
这里用到了XMLHttpRequest对象的onreadystatechange事件,该事件会在XMLHttpRequest对象的状态变化的时候触发,上网搜一搜XMLHttpRequest对象有五种状态:
0:仅仅创建了XMLHttpRequest对象,还未调用open()方法,【初始化未完成状态】
1:open()方法已经调用,但是还没有调用send()方法,【请求已经开始】
2:send()方法已经调用,【请求发送完成】
3:开始收到服务器的响应。
4:服务器响应完毕。
也就是说onreadystatechange会在,0-->1,1-->2,2-->3,3-->4的时候触发。
如果我们不做一些处理的话,很显然onreadystatechange会被触发四次。所以加了这个判断:if(xmlHttp.readyState==4&&xmlHttp.status==200),我们还关心服务器返回的状态码是否是200。
然后我们可以猜到:xmlHttp.responseText是从后台传递过来的数据,没错就是这样。
这里我们是这样传递参数给后台的:xmlHttp.send("username="+username);
后台就可以这样取到传递过来的数据:String username = request.getParameter("username");
BServlet的onPost方法中的代码如下【web.xml配置文件就不说了,都是工具自动完成的,没有大改】:
response.setContentType("text/html");
PrintWriter out = response.getWriter();
String username = request.getParameter("username");
boolean flag = new DBHelper().searchByName(username);//判断用户是否已经存在
String msg = flag==true?"User Already exists!":"";
out.print(msg);
out.print中的msg为后台与Ajax交互后最后传递过去的数据,与xmlHttp.responseText;对应。
中间就是封装的jdbc的操作了。
jdbc代码可看可不看,还是贴出来吧。
DBHelper
public class DBHelper {
public boolean searchByName(String name) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from user where name=?";
try {
conn = DBUtils.getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, name);
rs = ps.executeQuery();
if (rs.next()) {
return true;
} else {
return false;
}
} catch (SQLException e) {
e.printStackTrace();
}finally{
DBUtils.close(conn, ps, rs);
}
return false;
}
}
DBUtils
public class DBUtils {
private static String driver = "com.mysql.jdbc.Driver";
private static String url = "jdbc:mysql:///test";
private static String username = "root";
private static String password = "123";
static{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
/**获取数据库连接对象
* @return
*/
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(url,username,password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
/**关闭数据库连接资源
* @param con
* @param ps
* @param rs
*/
public static void close(Connection con,PreparedStatement ps,ResultSet rs){
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(ps!=null){
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
数据库中的user表如下:
就加了两条数据。
效果图再来一张