- 從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="width:80px;height:80px;display:none;background-color:red;"></div><br> <div id="div2" style="width:80px;height:80px;display:none;background-color:green;"></div><br> <div id="div3" style="width: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'); }); });