- 从WEB1.0开始讲起
十多年前,我们刚刚觉得网络引起我们的注意的时候,那时的网站用户量不像现在那么大,所以在1.0时代,多采用同步机制。我们隐约记得,注册一个账号通常需要反复提交,返回的信息会告诉你填入的信息哪里出现了错误,哪里不符合规范。注册一个账号常常需要刷新好多次页面,这样的不仅给服务器的效率产生阻碍,也不利于我们效率办公。所幸的是,当时的并发量不如现在的巨大。如果现在仍然采用同步机制,大概这个网站要不是不受欢迎,要不就是经常挂掉。
(百度偷来的图)
- 我所认识的WEB2.0
在不断接触2.0时代产品的同时,我们体验到了极大的方便与效率。比如我们现在注册的时候,按提交键肯定会一次注册成功了。(在设计上多按一次按键就会少很多用户量)这在现今社会快节奏的效应下,2.0时代完全符合现代人的品味。而2.0时代与1.0时代仅仅差别在于一个异步的HTTP提交方式--AJAX(Asynchronous Javascript And XML)。这个神奇的AJAX技术引领了一个时代的浪潮,而它并不是一种很大的技术框架,可以说它是一种“设计方式”。它的原理并不是那么困难,就是异步地提交一个标准的HTTP请求。而它发起的请求,通常不需要用户去点击浏览器内的按键,它可以在后台与服务器进行悄悄的通信,从而可以验证你的用户名是否合法,你的邮箱是否存在等等关键性信息。
2.0时代是讲求效率的时代,AJAX的出现结合同步机制,在不同场景中因地制宜,达到快速有效的解决用户数据交互问题,在学这个小技术的时候我更多的体会到了,设计这个技术的思维方式。
- 离不开的关键性协议:HTTP
超文本传输协议(HTTP,HigherText Transfer Protocol)我理解为一种通信协议。从我以前写socket的经验和计算机网络的TCP协议来看,它其实是TCP协议的一种变式。“它是一种无状态无连接的协议”。实际上它通信结束就马上cut掉连接了,它的底层仍然是socket类似的通信,而且连接是基于TCP协议。
说起HTTP,它不仅仅是只在B/S模型中应用广泛,虽然很多应用都是一个空的浏览器嵌入前端代码使用HTTP协议通信的,但在我看来它们也算是一种C/S模型。而HTTP协议的通信分为请求和响应两部分。
HTTP请求分为:请求行、消息头、请求体。我们使用HTTP访问服务器的时候,仍然是如socket一样采用http://IPAddr:Port这样的方式请求服务器。在建立连接后,浏览器发送请求行,浏览器发送请求头;这时候服务器会做出应答,发送响应信息和状态码,服务器发送响应头,服务器往浏览器发送数据,最后Web服务器关闭TCP连接。
HTTP响应信息:状态码,响应头,响应主体。状态码网上很多记录,主要是记得200,404,500,这些特殊的。
我们可以使用chrome浏览器来观察HTTP的请求和响应。请求头一般包括文本类型,编码方式,日期等。不做深入讨论。
有意思的是,html这个语言也主要分为head和body。这样的设计让我对HTTP这个协议加深了印象。
HTTP请求方法有5个,在WEB开发中最主要的还是GET和POST。在展开之前根据需求先大体总结一下,GET请求是请求少量信息的方法,有信息量上限。POST的请求是对大量数据交互的方法。
GET请求通常会把信息跟在url后面。GET请求没有请求体。比如下图。
POST请求是把数据放在请求体内发送。
在开发中需要谨记请求和响应这两个关键过程。
- 原生JavaScript的AJAX
由于长期写的都是后端语言,对这门函数式编程语言JavaScript生理上十分不适应。不过还好,我只需要熟悉怎么写它的Ajax就好了。它的过程十分简单。
首先,获取XHR对象,它被内嵌在浏览器中了,主要为了区别IE6这类特殊浏览器,不然直接调用XMLHttpRequest这个方法即可获取。
成功获取对象之后使用open()方法传入请求方法,请求url。这个onreadystatechange是一个回调函数,负责接收服务器响应数据的处理,这里类似将它重写,浏览器会调用这个方法处理返回数据。
send方法在GET请求中只需要传入null,因为send方法是把数据放在请求体内,只有POST方式才会往send里写数据。
回调函数的写法是按照模范代码抄写的。在responseText可以获得服务端写来的数据。
var XHR=false; function createXHR(){ if(window.XMLHttpRequest){ XHR=new XMLHttpRequest(); }else{ XHR=new ActiveXObject("Microsoft.XMLHTTP"); } } function checkUsername(){ var username=document.getElementById("check").value; createXHR(); XHR.open("get","checkUsername?username="+username,true); XHR.onreadystatechange=showMsgCallback; XHR.setRequestHeader("Content-type","application/x-www-form-urlencoded"); XHR.send(); } function showMsgCallback(){ if(XHR.readyState==4){ if(XHR.status==200){ var text=XHR.responseText.toString(); alert(text=='no'); console.log(text); if(text=="yes"){ alert(1); document.getElementById("msg").innerHTML="此用户名已注册!"; } else if(text=="no") { alert(2); document.getElementById("msg").innerHTML="此用户可以注册"; } } } }
配置Action的时候,我是将这个虚拟路径映射到checkUsername()方法上。后端要获得Ajax的数据,需要获得reques对象,写数据需要使用response对象。这就是为什么需要谨记请求和响应这两个过程。
import java.io.IOException; import java.io.PrintWriter; import javax.management.relation.RoleUnresolved; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.SystemUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class CheckAction extends ActionSupport{ private String name; public String getUsername() { return name; } public void setUsername(String name) { this.name = name; } public void checkUsername() { HttpServletRequest request = ServletActionContext.getRequest(); name = request.getParameter("name"); System.out.println(name); HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = null; try { out = response.getWriter(); } catch (IOException e) { e.printStackTrace(); } if (name.equals("ctk")) { out.print("no"); out.flush(); } else { out.print("yes"); out.flush(); } out.close(); } public String execute(){ return SUCCESS; } }
- Jquery是个什么鬼
我本人对这种带$和#的语言表示生理上十分不适应。虽然它很简单。Jquery是一个封装javascript的框架。它的目的是make js easier。Jquery的核心就是一个选择器。它张这样---$()。你在html上定义的id可以通过#来锁定。什么class,css这些东西我都不想理了,太卵烦了。它的代码让人感觉很清爽,清爽得让我看不懂。
$(document).ready(function() { $('#button1').click(function() { var text = $('#msg1'); $.ajax({ type : "POST", url : "jquery", data : "username=ssss", dataType : 'text', success : function(result) { if (result=="success") { text.text(""); text.append("成功"); }else{ text.text(""); text.append("失败"); } }, error : function() { text.text(""); text.append("操作出错"); } }); }); }); $(document).ready(function(){ $('#button2').click(function(){ var text = $('#msg2'); $.post('jquery', 'username=xxxx',function(result){ if (result==="success") { text.text("成功"); }else{ text.text("失败"); } },'text'); }); }); $(document).ready(function(){ $('#button3').click(function(){ var text = $('#msg3'); $.get('jquery','username=zzzzz',function(result){ if (result==="success") { text.text("成功"); }else{ text.text("失败"); } }); }); });
这是我写的三种Jquery的ajax写法。它带着html是长这样。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ajax交互</title> <script src="jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function() { $('#button1').click(function() { var text = $('#msg1'); $.ajax({ type : "POST", url : "jquery", data : "username=ssss", dataType : 'text', success : function(result) { if (result=="success") { text.text(""); text.append("成功"); }else{ text.text(""); text.append("失败"); } }, error : function() { text.text(""); text.append("操作出错"); } }); }); }); $(document).ready(function(){ $('#button2').click(function(){ var text = $('#msg2'); $.post('jquery', 'username=xxxx',function(result){ if (result==="success") { text.text("成功"); }else{ text.text("失败"); } },'text'); }); }); $(document).ready(function(){ $('#button3').click(function(){ var text = $('#msg3'); $.get('jquery','username=zzzzz',function(result){ if (result==="success") { text.text("成功"); }else{ text.text("失败"); } }); }); }); </script> </head> <body> <button id="button1">点击使用$ajax发送</button> <span id="msg1"></span> <br/> <button id="button2">点击使用$post发送</button> <span id="msg2"></span> <br/> <button id="button3">点击使用$get发送</button> <span id="msg3"></span> <br/> </body> </html>
然后我在网上搜集到的这三种api的图解。
刚开始写的时候有些不适应,最后感觉看着api,这种设计模式挺轻松的。
package servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @WebServlet("/jquery") public class JqueryServlet extends HttpServlet{ public JqueryServlet() { super(); // TODO Auto-generated constructor stub } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username=request.getParameter("username"); System.out.println(username); response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out=response.getWriter(); out.print("success"); out.flush(); out.close(); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub doGet(request, response); } }
每次写jquery的时候记得要导入jquery的源码。
- AJAX请求Struts2的Action
起初我一直很疑惑,如何请求Action,那时因为对HTTP协议的理解不太深入。谨记请求和响应之后,AJAX的请求不过就是一个HTTP的请求,只要把请求路径和Action名字对应,一切豁然开朗。
<%@ 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"> <%@ taglib prefix="s" uri="/struts-tags" %> <%@ taglib prefix="sx" uri="/struts-dojo-tags" %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>AJAX范例</title> <sx:head/> <script src="jquery.min.js" type="text/javascript"></script> <script type="text/javascript"> $(document).ready(function(){ $('#usrname').blur(function(){ $.ajax({ type : "POST", url : "checkUsername", data : 'name='+$('#usrname').val(), dataType : 'text', success:function(data){ if(data==='yes') $('#msg').text('可以登录'); else if(data==='no') $('#msg').text('无法登录'); } }); }); }); </script> </head> <body> <center> <form action=""> <span id="msg"></span><br/> 用户名:<input id="usrname" name="name" type="text"/> <br/> 密码:<input name="password" type="password"/> <br/> <button type="submit">提交</button> <button type="reset">重置</button> </form> </center> </body> </html>
package ActionPackage; import java.io.IOException; import java.io.PrintWriter; import javax.management.relation.RoleUnresolved; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.SystemUtils; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class CheckAction extends ActionSupport{ private String name; public String getUsername() { return name; } public void setUsername(String name) { this.name = name; } public void checkUsername() { HttpServletRequest request = ServletActionContext.getRequest(); name = request.getParameter("name"); System.out.println(name); HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType("text/html"); response.setCharacterEncoding("utf-8"); PrintWriter out = null; try { out = response.getWriter(); } catch (IOException e) { e.printStackTrace(); } if (name.equals("ctk")) { out.print("no"); out.flush(); } else { out.print("yes"); out.flush(); } out.close(); } public String execute(){ return SUCCESS; } }
<action name="checkUsername" class="ActionPackage.CheckAction" method="checkUsername"> </action>
- 后记
首先我觉得书上写不清楚,网上的也是很杂,不过摸着石头过河的感觉还是很不错的。学了一些前端的知识,写了写前端的代码,也长了一些知识。附带一个jquery的动画。html有个失去焦点事件和点击事件,都是设计所必要的。对当代网页架构都有了新的认识,前后端分离的感觉挺fashion的。不积跬步无以至千里。
<html> <head> <title>this is a test page</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="jquery.min.js" type="text/javascript"></script> <script src="jq.js" type="text/javascript"></script> </head> <body> <div> <p> 1.click me! </p> <p> 2.click me! </p> </div> <button id="in">点击淡入 div 元素。</button> <button id="out">点击淡出 div 元素。</button> <div id="div1" style="80px;height:80px;display:none;background-color:red;"></div><br> <div id="div2" style="80px;height:80px;display:none;background-color:green;"></div><br> <div id="div3" style="80px;height:80px;display:none;background-color:blue;"></div> </body> </html> $(document).ready(function(){ $("p").click(function(){ $(this).hide(); }) ; }); $(document).ready(function(){ $("#in").click(function(){ $("#div1").fadeIn(); $("#div2").fadeIn("slow"); $("#div3").fadeIn(3000); }); }); $(document).ready(function(){ $("#out").click(function(){ $("#div1").fadeOut(); $("#div2").fadeOut("slow"); $("#div3").fadeOut(3000); }); });
Ajax还有个load方法,请求载入内容的。
$(document).ready(function(){ $('#ajaxrequest').click(function(){ $('#directory').load('hello.html'); alert('loaded'); }); });