我的Ajax的学习也是刚刚开始,也基本有了大致的概念,最近在慕课网上学习了一个老师的课程,讲得蛮好的,很感谢老师,虽然他的项目的服务器是PHP写的,哈哈!所以我不得不自己的花点时间自己重新写一个基本的java Servlet服务器。也是很好的巩固了自己的知识吧。但是不要忘了,重点还是在Ajax的学习上喔。
我们都知道Ajax的核心是XMLHttpRequest,这是实现异步请求和响应的基本对象。当然我的代码中没考虑到IE6以前版本的兼容,尴尬。因为我想让代码看起来尽量的简单清晰。
我的这个简单的程序是一个添加人员信息和根据用户名查询信息的简单程序。服务端程序包括Person实体类,PersonService业务逻辑类,然后就是添加和查询的两个Servlet,分别是AddServlet和SearchServlet。大家对相关的知识也不陌生,那我就直接上代码吧。喔,对了,这里的存储信息的方式用的是properties文件,也是很容易理解的一个点。
Person.java
public class Person { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }PersonService.java
public class PersonService { private static Properties pro; private static PersonService ps; public static PersonService instance(){ if(ps == null){ ps = new PersonService(); } return ps; } // 解析properties文件,将properties的文件内容由输入流存入变量pro中 public static Properties loadPerson() throws IOException{ File f = new File("Person.properties"); if(!f.exists()){ f.createNewFile(); } FileInputStream fi = new FileInputStream(f); pro = new Properties(); pro.load(fi); return pro; } // 将数据存入properties文件 public static boolean savePerson() throws IOException{ if(pro == null){ return false; } File f = new File("Person.properties"); pro.store(new FileOutputStream(f), "new person inject"); return true; } public static Person SearchPerson(String name) throws IOException{ Person person = new Person(); if(pro == null){ pro = loadPerson(); } String pass = pro.getProperty(name); if(pass!=null){ person.setUsername(name); person.setPassword(pass); } return person; } public static boolean addPerson(String name,String pass) throws Exception{ if(pro == null){ pro = loadPerson(); } if(pro.containsKey(name)){ throw new Exception("用户名已经存在,请重新选择用户名!"); } pro.setProperty(name, pass); savePerson(); return true; } } AddServlet.java @WebServlet("/AddServlet") public class AddServlet extends HttpServlet { private static final long serialVersionUID = 1L; public AddServlet() { super(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); String res = null; try { if(PersonService.addPerson(username, password)){ res="恭喜,数据插入成功"; } else{ res="抱歉,数据插入失败"; } } catch (Exception e) { e.printStackTrace(); } response.setContentType("text/html;charset=GBK"); PrintWriter pw = response.getWriter(); pw.println(res); } } SearchServlet.java @WebServlet("/SearchServlet") public class SearchServlet extends HttpServlet { private static final long serialVersionUID = 1L; public SearchServlet() { super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String name = request.getParameter("username1"); String res = null; Person person = PersonService.SearchPerson(name); if(person ==null){ res = "对不起,查询失败"; }else{ res = person.getUsername()+person.getPassword(); } response.setContentType("text/html;charset=GBK"); PrintWriter pw = response.getWriter(); pw.println(res); } } 上面的代码中的两个Servlet的Mapping地址是通过注解来确定的。还有一个,细心的同志会发现上面的两个Servlet一个使用的是doGet方法,一个是doPost方法处理客户端请求,这么做的原因是:在下文中我想测试Ajax中两种提交方式的不同。好了,我们再来看看Ajax实现异步的流程。首先,你得手握一个核心对象,没错,你需要初始化一个XMLHttpRequest
其次,有了对象,你需要去建立和处理你这个请求有关逻辑的连接,这里用到的是open()方法
然后,你就可以提交请求了,至于是什么提交方式,开发者可以在上面的open()方法指定,区别见下文。
最后,请求响应成不成功呢?成功了如何接收参数呢?这时我们就得看看状态码和readyState了。
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>动态Ajax界面</title> <style type="text/css"> body,input{ font-family:"隶书"; font-size:30px; line-height:30px; } </style> </head> <body> <div> <!--本示例对应的是jspchat项目中的一个偏项目--> <h1>在下面的输入框输入你想要查询的名字</h1> <input type="text" name="username1" id="username1"> <input type="submit" id="btn1" value="查询"><br> <p id="p1"></p> <br> <h1>在下面的输入框输入你想要添加人的信息</h1> username:<input type="text" name="username" id="username"><br> password:<input type="password" name="password" id="password"><br> <input type="submit" id="btn2" value="添加"><br> <p id="p2"></p> </div> <script type="text/javascript"> var btn1 = document.getElementById("btn1"); var btn2 = document.getElementById("btn2"); btn1.onclick = function() { // 查询逻辑 var request = new XMLHttpRequest(); request.open("get", "SearchServlet?username1="+document.getElementById("username1").value); request.send(); request.onreadystatechange = function() { if(request.readyState===4){ if(request.status===200){ document.getElementById("p1").innerHTML=request.responseText; }else{ alert("发生错误,"+request.status); } } } }; btn2.onclick = function() { // 查询逻辑 var request = new XMLHttpRequest(); var data = "username="+document.getElementById('username').value+"&password="+document.getElementById('password').value; request.open("post", "AddServlet"); request.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); request.send(data); request.onreadystatechange = function() { if(request.readyState===4){ if(request.status===200){ document.getElementById("p2").innerHTML=request.responseText; }else{ alert("发生错误,"+request.status); } } } }; </script> </body> </html>有没有注意到一个问题,这个html不存在表单,对,这就是异步加载,不需要用户一次次的提交表单,然后等待页面的再次重新下载,Ajax可以将请求异步的发送出去,异步的接收响应信息,完全不干扰主线程的执行。本实例所有的逻辑都在JavaScript中实现。我们对比来看区别。
代码中的open方法只有两个参数,第一个参数是请求类型,不区分大小写;第二个参数是请求的URL;其实还可以指定第三个参数,决定是否异步发送请求,默认值是true。
好,接着代码前的那个问题,认真观察发现,Get请求在连接阶段就将请求体组装好了,但是post请求是在发送的时候才将请求内容加进去。所以send()被前者使用时一般无参,后者使用则应该有参。另外,使用post请求时指定了请求头,想必大家对于这个application/x-www-form-urlencoded是比较熟悉的,不熟悉的话回忆下下面的代码。
// URLEncoder将输入的非西欧字符转换为application/x-www-form-urlencoded MIME字符,也就是浏览器中的乱码 String keyword = URLEncoder.encode("王二狗JavaEE","utf-8"); System.out.println(keyword); // 再次将这个字符串转为原来的字符串 String keyword1 = URLDecoder.decode("王二狗JavaEE","utf-8"); System.out.println(keyword1);回忆起来了吗?对,这是Socket编程中的知识。不了解去查阅资料喔。
回到上面的话题,请求是否完成,是否成功我们得判断,怎么判断呢?XMLHttpRequest有一个readyState变量,不同的值代表不同的状态,0代表请求未初始化,1代表请求已经初始化,2代表请求已经发送,3代表请求正在处理中,4代表请求处理完成。对,写一个方法监听它的变化,所以就有了上面的代码。
至于status那个的意思是状态码,就是和404,500什么的一套规范的状态码信息,200代表的是成功,无BUG。
返回的数据被存储在ResponseText中,这也是最常用的用来存放数据的响应类型,还有一个常用的就是ResponseXML。当然还有很多的方法需要我们去学习。加油!