. 增強(qiáng)HttpServletResponse對象
1. 實(shí)現(xiàn)一個(gè)增強(qiáng)的HttpServletResponse類,需要繼承javax.servlet.http.HttpServletRequestWrapper類,通過重寫自己需要增強(qiáng)的方法來實(shí)現(xiàn)(這種模式就叫做裝飾者模式),使用該增強(qiáng)類在加上過濾器就可以實(shí)現(xiàn)無編碼轉(zhuǎn)換處理代碼。
public class MyRequest extends HttpServletRequestWrapper{ private HttpServletRequest req; public MyRequest(HttpServletRequest request) { super(request); req=request; } @Override public String getParameter(String name) { //解決編碼問題,無論是post還是get請求,都不需要在業(yè)務(wù)代碼中對編碼再處理 String method=req.getMethod(); if("get".equalsIgnoreCase(method)){ try { String str=req.getParameter(name); byte[] b=str.getBytes("iso8859-1"); String newStr=new String(b, "utf-8"); return newStr; } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else if("post".equalsIgnoreCase(method)){ try { req.setCharacterEncoding("utf-8"); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //絕對不能刪除此行代碼,因?yàn)榇诵写a返回的就是編碼之后的數(shù)據(jù) return super.getParameter(name); } }
在過濾器中應(yīng)用
public class FilterTest4 implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //生成增強(qiáng)的HttpServletRequest對象 HttpServletRequest req=(HttpServletRequest) request; MyRequest myReq=new MyRequest(req); //將增強(qiáng)的HttpServletRequest對象傳入過濾器執(zhí)行鏈中,在后面?zhèn)魅氲膔equest對象都會是增強(qiáng)的HttpServletRequest對象 chain.doFilter(myReq, response); } @Override public void destroy() {} }
2. 文件上傳原理過程
1. JavaWeb中實(shí)現(xiàn)文件上傳:
<html> <head> <title>My JSP 'upload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <form action="" method="post" enctype="multipart/form-data"> <input type="text" name="name"> 請選擇文件:<input type="file" name="upload"> <input type="submit" value="上傳"> </form> </body> </html>
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { /** * 1. 創(chuàng)建磁盤文件項(xiàng)工廠類 DiskFileItemFactory * 2. 創(chuàng)建核心解析Request類 ServletFileUpload * 3. 開始解析Request對象中的數(shù)據(jù),并返回一個(gè)List集合 * 4. List中包含表單中提交的內(nèi)容 * 5. 遍歷集合,獲取內(nèi)容 */ DiskFileItemFactory fac=new DiskFileItemFactory(); ServletFileUpload upload=new ServletFileUpload(fac); upload.setHeaderEncoding("utf-8");//防止中文的文件名亂碼 try { List<FileItem> fileItems = upload.parseRequest(req); for(FileItem item:fileItems){ //有可能是普通文本項(xiàng),比如<input type="text">標(biāo)簽提交上來的字符串 //也有可能是<input type="submit" value="上傳">上傳的文件 //文件項(xiàng)與普通項(xiàng)有不同的API來處理 //首先判斷是普通文本項(xiàng)還是文件項(xiàng), if(item.isFormField()){ //true表示普通文本項(xiàng) //獲取文本項(xiàng)的name屬性值 String name=item.getFieldName(); //獲取對應(yīng)的文本 String value=item.getString("utf-8");//防止中文亂碼 System.out.println(name+":"+value); }else{ //false表示文件項(xiàng) //先獲取文件名稱 String name=item.getName(); //獲取文件項(xiàng)的輸入流 InputStream in=item.getInputStream(); //獲取服務(wù)器端文件存儲的目標(biāo)磁盤路徑 String path=getServletContext().getRealPath("/upload"); System.out.println(path); //獲取輸出流,輸出到本地文件中 OutputStream out=new FileOutputStream(path+"/"+name); //寫入數(shù)據(jù) int len=0; byte[] b=new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
注意:在文件上傳時(shí),會將form表單的屬性enctype屬性值為"multipart/form-data",當(dāng)提交到服務(wù)端后,無法使用 req.getParameter(name) 方法來獲取到內(nèi)容,只有通過上面的方法來獲取文本項(xiàng)。
2. 文件上傳相關(guān)核心類:
//改進(jìn)上面的文件上傳代碼,添加一個(gè)臨時(shí)文件 public class UploadServlet extends HttpServlet{ @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { DiskFileItemFactory fac=new DiskFileItemFactory(); fac.setSizeThreshold(1024*1024);//設(shè)置緩沖區(qū)為1mb //設(shè)置臨時(shí)文件的本地磁盤存儲路徑 File repository=new File(getServletContext().getRealPath("/temp")); fac.setRepository(repository); ServletFileUpload upload=new ServletFileUpload(fac); upload.setHeaderEncoding("utf-8");//防止中文的文件名亂碼 try { List<FileItem> fileItems = upload.parseRequest(req); for(FileItem item:fileItems){ if(item.isFormField()){ String name=item.getFieldName(); String value=item.getString(); String value=item.getString("utf-8");//防止中文亂碼 System.out.println(name+":"+value); }else{ String name=item.getName(); InputStream in=item.getInputStream(); String path=getServletContext().getRealPath("/upload"); System.out.println(path); OutputStream out=new FileOutputStream(path+"/"+name); int len=0; byte[] b=new byte[1024]; while((len=in.read(b))!=-1){ out.write(b,0,len); } in.close(); out.close(); } } } catch (FileUploadException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
3. 實(shí)現(xiàn)多文件上傳(需要js技術(shù)):主要是更改jsp頁面,通過js代碼來添加多個(gè)文件進(jìn)行上傳,服務(wù)器代碼無需更改
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html; charset=utf-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'upload.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <script type="text/javascript"> function run(){ var div=document.getElementById("divId"); div.innerHTML+= "<div><input type='file' name='upload'><input type='button' value='刪除' onclick='del(this)'></div>" } function del(presentNode){ var div=document.getElementById("divId"); div.removeChild(presentNode.parentNode); } </script> <div> 多文件上傳<br/> <form action="/Servlet/upload" method="post" enctype="multipart/form-data"> <input type="button" value="添加" onclick="run()"><br/> <div id="divId"> </div> <input type="submit" value="上傳"> </form> </div> </body> </html>
4. 關(guān)于文件上傳的一些問題:
3. 文件下載
1. 傳統(tǒng)文件下載方式有超鏈接下載或者后臺程序下載兩種方式。通過超鏈接下載時(shí),如果瀏覽器可以解析,那么就會直接打開,如果不能解析,就會彈出下載框;而后臺程序下載就必須通過兩個(gè)響應(yīng)頭和一個(gè)文件的輸入流。
2. 后臺程序下載:
JSP指令用來設(shè)置整個(gè)JSP頁面相關(guān)的屬性,如網(wǎng)頁的編碼方式和腳本語言。
語法格式如下:
<%@ directive attribute="value" %>
指令可以有很多個(gè)屬性,它們以鍵值對的形式存在,并用逗號隔開。
JSP中的三種指令標(biāo)簽:
指令 | 描述 |
---|---|
<%@ page ... %> | 定義網(wǎng)頁依賴屬性,比如腳本語言、error頁面、緩存需求等等 |
<%@ include ... %> | 包含其他文件 |
<%@ taglib ... %> | 引入標(biāo)簽庫的定義 |
Page指令
Page指令為容器提供當(dāng)前頁面的使用說明。一個(gè)JSP頁面可以包含多個(gè)page指令。
Page指令的語法格式:
<%@ page attribute="value" %>
等價(jià)的XML格式:
<jsp:directive.page attribute="value" />
屬性
下表列出與Page指令相關(guān)的屬性:
屬性 | 描述 |
---|---|
buffer | 指定out對象使用緩沖區(qū)的大小 |
autoFlush | 控制out對象的 緩存區(qū) |
contentType | 指定當(dāng)前JSP頁面的MIME類型和字符編碼 |
errorPage | 指定當(dāng)JSP頁面發(fā)生異常時(shí)需要轉(zhuǎn)向的錯(cuò)誤處理頁面 |
isErrorPage | 指定當(dāng)前頁面是否可以作為另一個(gè)JSP頁面的錯(cuò)誤處理頁面 |
extends | 指定servlet從哪一個(gè)類繼承 |
import | 導(dǎo)入要使用的Java類 |
info | 定義JSP頁面的描述信息 |
isThreadSafe | 指定對JSP頁面的訪問是否為線程安全 |
language | 定義JSP頁面所用的腳本語言,默認(rèn)是Java |
session | 指定JSP頁面是否使用session |
isELIgnored | 指定是否執(zhí)行EL表達(dá)式 |
isScriptingEnabled | 確定腳本元素能否被使用 |
Include指令
JSP可以通過include指令來包含其他文件。被包含的文件可以是JSP文件、HTML文件或文本文件。包含的文件就好像是該JSP文件的一部分,會被同時(shí)編譯執(zhí)行。
Include指令的語法格式如下:
<%@ include file="文件相對 url 地址" %>
include 指令中的文件名實(shí)際上是一個(gè)相對的 URL 地址。
如果您沒有給文件關(guān)聯(lián)一個(gè)路徑,JSP編譯器默認(rèn)在當(dāng)前路徑下尋找。
等價(jià)的XML語法:
<jsp:directive.include file="文件相對 url 地址" />
Taglib指令
JSP API允許用戶自定義標(biāo)簽,一個(gè)自定義標(biāo)簽庫就是自定義標(biāo)簽的集合。
Taglib指令引入一個(gè)自定義標(biāo)簽集合的定義,包括庫路徑、自定義標(biāo)簽。
Taglib指令的語法:
<%@ taglib uri="uri" prefix="prefixOfTag" %>
uri屬性確定標(biāo)簽庫的位置,prefix屬性指定標(biāo)簽庫的前綴。
等價(jià)的XML語法:
<jsp:directive.taglib uri="uri" prefix="prefixOfTag" />
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
言:在CGI(通用網(wǎng)關(guān)接口)編程風(fēng)行的日子,人們紛紛尋思簡化并讓其更加靈活的新方法和新技術(shù),包括PHP、JSP、ASP。1997年SUN公司推出了servlet,1999年初,SUN公司推出了JSP,實(shí)際上在servlet基礎(chǔ)上修改而成。JSP即Java服務(wù)器頁面(Java Server Page),將HTML和JAVA代碼使用某種方式結(jié)合起來,完成前后端的有效交互。本文通過JSP歷史回顧和應(yīng)用總結(jié)來審視過去和開拓未來。
其實(shí),從現(xiàn)在看來JSP依然極具魅力,據(jù)了解很多JSP老項(xiàng)目還在維護(hù)。下面使用STS作為IDE構(gòu)建一個(gè)實(shí)例項(xiàng)目,先體驗(yàn)其效果。
如下圖,使用new dynamic web project創(chuàng)建項(xiàng)目:
進(jìn)入preferences修改JSP文件的編碼:
新增一個(gè)JSP文件到WebContent目錄,如下
然后檢查并修改編碼,應(yīng)該都是UTF-8,如下圖:
如果不是,就修改。
選中項(xiàng)目名稱,點(diǎn)郵件菜單的Run as ...-->Run on server
之后出現(xiàn)如下界面:
若沒有現(xiàn)存的tomcat server,就自己加一個(gè)。點(diǎn)Finish。然后自動調(diào)用chrome,界面如下:
自動調(diào)用瀏覽器設(shè)置的地方是windows-->Web browser菜單:
(1)顯示ip地址:getRemoteAddr
(2)變量聲明<%! %>
(3)表達(dá)式<%=%>
語法 | 描述 |
<%-- 注釋 --%> | JSP注釋,注釋內(nèi)容不會被發(fā)送至瀏覽器甚至不會被編譯 |
<!-- 注釋 --> | HTML注釋,通過瀏覽器查看網(wǎng)頁源代碼時(shí)可以看見注釋內(nèi)容 |
<\% | 代表靜態(tài) <%常量 |
%\> | 代表靜態(tài) %> 常量 |
\' | 在屬性中使用的單引號 |
\" | 在屬性中使用的雙引號 |
指令 | 描述 |
<%@ page ... %> | 定義頁面的依賴屬性,比如腳本語言、error頁面、緩存需求等等 |
<%@ include ... %> | 包含其他文件 |
<%@ taglib ... %> | 引入標(biāo)簽庫的定義,可以是自定義標(biāo)簽 |
屬性 | 描述 |
buffer | 指定out對象使用緩沖區(qū)的大小 |
autoFlush | 控制out對象的 緩存區(qū) |
contentType | 指定當(dāng)前JSP頁面的MIME類型和字符編碼 |
errorPage | 指定當(dāng)JSP頁面發(fā)生異常時(shí)需要轉(zhuǎn)向的錯(cuò)誤處理頁面 |
isErrorPage | 指定當(dāng)前頁面是否可以作為另一個(gè)JSP頁面的錯(cuò)誤處理頁面 |
extends | 指定servlet從哪一個(gè)類繼承 |
import | 導(dǎo)入要使用的Java類 |
info | 定義JSP頁面的描述信息 |
isThreadSafe | 指定對JSP頁面的訪問是否為線程安全 |
language | 定義JSP頁面所用的腳本語言,默認(rèn)是Java |
session | 指定JSP頁面是否使用session |
isELIgnored | 指定是否執(zhí)行EL表達(dá)式 |
isScriptingEnabled | 確定腳本元素能否被使用 |
行為標(biāo)簽語法:<jsp:行為名稱 attribute="value" />
語法 | 描述 |
jsp:include | 用于在當(dāng)前頁面中包含靜態(tài)或動態(tài)資源 |
jsp:useBean | 尋找和初始化一個(gè)JavaBean組件 |
jsp:setProperty | 設(shè)置 JavaBean組件的值 |
jsp:getProperty | 將 JavaBean組件的值插入到 output中 |
jsp:forward | 從一個(gè)JSP文件向另一個(gè)文件傳遞一個(gè)包含用戶請求的request對象 |
jsp:plugin | 用于在生成的HTML頁面中包含Applet和JavaBean對象 |
jsp:element | 動態(tài)創(chuàng)建一個(gè)XML元素 |
jsp:attribute | 定義動態(tài)創(chuàng)建的XML元素的屬性 |
jsp:body | 定義動態(tài)創(chuàng)建的XML元素的主體 |
jsp:text | 用于封裝模板數(shù)據(jù) |
使用bean是最好用的行為標(biāo)簽,例如,我們創(chuàng)建一個(gè)java類:
然后,在JSP中使用useBea/setProperty/getProperty三個(gè)行為標(biāo)簽:
測試:
對象 | 描述 |
request | HttpServletRequest類的實(shí)例 |
response | HttpServletResponse類的實(shí)例 |
out | PrintWriter類的實(shí)例,用于把結(jié)果輸出至網(wǎng)頁上 |
session | HttpSession類的實(shí)例 |
application | ServletContext類的實(shí)例,與應(yīng)用上下文有關(guān) |
config | ServletConfig類的實(shí)例 |
pageContext | PageContext類的實(shí)例,提供對JSP頁面所有對象以及命名空間的訪問 |
page | 類似于Java類中的this關(guān)鍵字 |
Exception | Exception類的對象,代表發(fā)生錯(cuò)誤的JSP頁面中對應(yīng)的異常對象 |
判斷語句包括兩種:if else和switch case
示例如下:
循環(huán)語句包括兩種:for和while
示例如下:
類別 | 操作符 | 結(jié)合性 |
后綴 | () [] . (點(diǎn)運(yùn)算符) | 左到右 |
一元 | ++ - - ! ~ | 右到左 |
可乘性 | * / % | 左到右 |
可加性 | + - | 左到右 |
移位 | >> >>> << | 左到右 |
關(guān)系 | > >= < <= | 左到右 |
相等/不等 | == != | 左到右 |
位與 | & | 左到右 |
位異或 | ^ | 左到右 |
位或 | | | 左到右 |
邏輯與 | && | 左到右 |
邏輯或 | || | 左到右 |
條件判斷 | ?: | 右到左 |
賦值 | = += -= *= /= %= >>= <<= &= ^= |= | 右到左 |
逗號 | , | 左到右 |
布爾值(boolean):true 和 false;
整型(int):與 Java 中的一樣;
浮點(diǎn)型(float):與 Java 中的一樣;
字符串(string):以單引號或雙引號開始和結(jié)束;
Null:null。
以下提供一個(gè)例子來說明:
(1)創(chuàng)建FormProcess.jsp文件:
其中提供了兩個(gè)input輸入框。
(2)再創(chuàng)建FormProcessMain.jsp文件,如下:
其中使用request對象的getParameter方法來獲取Get參數(shù)。
JSP過濾器實(shí)際上和Servlet過濾器一樣。
以下通過示例來說明:
(1)在web.xml中增加一個(gè)過濾器:
(2)然后創(chuàng)建過濾器處理類com.hunting.LogFilter,如下:
(1)核心標(biāo)簽:
標(biāo)簽 | 描述 |
<c:out> | 用于在JSP中顯示數(shù)據(jù),就像<%= ... > |
<c:set> | 用于保存數(shù)據(jù) |
<c:remove> | 用于刪除數(shù)據(jù) |
<c:catch> | 用來處理產(chǎn)生錯(cuò)誤的異常狀況,并且將錯(cuò)誤信息儲存起來 |
<c:if> | 與我們在一般程序中用的if一樣 |
<c:choose> | 本身只當(dāng)做<c:when>和<c:otherwise>的父標(biāo)簽 |
<c:when> | <c:choose>的子標(biāo)簽,用來判斷條件是否成立 |
<c:otherwise> | <c:choose>的子標(biāo)簽,接在<c:when>標(biāo)簽后,當(dāng)<c:when>標(biāo)簽判斷為false時(shí)被執(zhí)行 |
<c:import> | 檢索一個(gè)絕對或相對 URL,然后將其內(nèi)容暴露給頁面 |
<c:forEach> | 基礎(chǔ)迭代標(biāo)簽,接受多種集合類型 |
<c:forTokens> | 根據(jù)指定的分隔符來分隔內(nèi)容并迭代輸出 |
<c:param> | 用來給包含或重定向的頁面?zhèn)鬟f參數(shù) |
<c:redirect> | 重定向至一個(gè)新的URL. |
<c:url> | 使用可選的查詢參數(shù)來創(chuàng)造一個(gè)URL |
(2)格式化標(biāo)簽:
標(biāo)簽 | 描述 |
<fmt:formatNumber> | 使用指定的格式或精度格式化數(shù)字 |
<fmt:parseNumber> | 解析一個(gè)代表著數(shù)字,貨幣或百分比的字符串 |
<fmt:formatDate> | 使用指定的風(fēng)格或模式格式化日期和時(shí)間 |
<fmt:parseDate> | 解析一個(gè)代表著日期或時(shí)間的字符串 |
<fmt:bundle> | 綁定資源 |
<fmt:setLocale> | 指定地區(qū) |
<fmt:setBundle> | 綁定資源 |
<fmt:timeZone> | 指定時(shí)區(qū) |
<fmt:setTimeZone> | 指定時(shí)區(qū) |
<fmt:message> | 顯示資源配置文件信息 |
<fmt:requestEncoding> | 設(shè)置request的字符編碼 |
(3)SQL標(biāo)簽:
標(biāo)簽 | 描述 |
<sql:setDataSource> | 指定數(shù)據(jù)源 |
<sql:query> | 運(yùn)行SQL查詢語句 |
<sql:update> | 運(yùn)行SQL更新語句 |
<sql:param> | 將SQL語句中的參數(shù)設(shè)為指定值 |
<sql:dateParam> | 將SQL語句中的日期參數(shù)設(shè)為指定的java.util.Date 對象值 |
<sql:transaction> | 在共享數(shù)據(jù)庫連接中提供嵌套的數(shù)據(jù)庫行為元素,將所有語句以一個(gè)事務(wù)的形式來運(yùn)行 |
(4)XML標(biāo)簽:
標(biāo)簽 | 描述 |
<x:out> | 與<%= ... >,類似,不過只用于XPath表達(dá)式 |
<x:parse> | 解析 XML 數(shù)據(jù) |
<x:set> | 設(shè)置XPath表達(dá)式 |
<x:if> | 判斷XPath表達(dá)式,若為真,則執(zhí)行本體中的內(nèi)容,否則跳過本體 |
<x:forEach> | 迭代XML文檔中的節(jié)點(diǎn) |
<x:choose> | <x:when>和<x:otherwise>的父標(biāo)簽 |
<x:when> | <x:choose>的子標(biāo)簽,用來進(jìn)行條件判斷 |
<x:otherwise> | <x:choose>的子標(biāo)簽,當(dāng)<x:when>判斷為false時(shí)被執(zhí)行 |
<x:transform> | 將XSL轉(zhuǎn)換應(yīng)用在XML文檔中 |
<x:param> | 與<x:transform>共同使用,用于設(shè)置XSL樣式表 |
下面從前后端分離角度展現(xiàn)JSP的產(chǎn)生和發(fā)展脈絡(luò)。
1957年美國國防部(DoD)組建了高級研究計(jì)劃局(ARPA)。1961年7月,MIT工程師Leonard Kleinrock發(fā)表Information Flow in Large Communication Nets論文。1962年8月, MIT工程師J.C.R. Licklider和W. Clark發(fā)表On-Line Man Computer Communication論文。1967 2月,在ARPA IPTO PI會議上,Larry Roberts組織了有關(guān)ARPANET設(shè)計(jì)方案的討論?;ヂ?lián)網(wǎng)雛形ARPANET由此產(chǎn)生。
互聯(lián)網(wǎng)最初的目的是訪問和復(fù)制文件從一臺計(jì)算機(jī)到另一臺遠(yuǎn)程計(jì)算機(jī),兩臺計(jì)算機(jī)之間有網(wǎng)絡(luò),但速度慢,而且經(jīng)常專用于大學(xué)或者研究機(jī)構(gòu)是昂貴的,不支持大規(guī)模用戶。1970年,ARPANET主機(jī)開始使用網(wǎng)絡(luò)控制協(xié)議(NCP),這就是后來的傳輸控制協(xié)議(TCP)的雛形。
人們基于TCP/IP構(gòu)建了更快的網(wǎng)絡(luò),其中應(yīng)用層文件傳輸協(xié)議(FTP)規(guī)范提供了交換這些文件的標(biāo)準(zhǔn)方法。1973年,文件傳輸協(xié)議(FTP)推出,用于在異構(gòu)系統(tǒng)之間交換文件。FTP傳輸?shù)奈募⒉荒苡行Р榭矗虼税l(fā)明了超文本標(biāo)記語言(HTML),使我們能夠在互聯(lián)網(wǎng)上看到文檔。
1989年蒂姆伯納斯-李寫了一份關(guān)于建立一個(gè)通過網(wǎng)絡(luò)傳輸超文本系統(tǒng)的報(bào)告,其中創(chuàng)建了單行 HTTP 協(xié)議,這個(gè)協(xié)議在1991年被命名為HTTP/0.9,萬維網(wǎng)由此產(chǎn)生,1996年超文本傳送協(xié)議HTTP 1.0發(fā)布。
盡管FTP可以傳輸HTML文件,但是并沒有提供有效小文件傳輸機(jī)制和無狀態(tài)管理能力,超文本傳輸協(xié)議(HTTP)才被發(fā)明出來專門用于傳輸HTML文檔,HTTP是一種無連接/無狀態(tài)協(xié)議,這使得許多短連接更加有效,而且可以不使用密碼就可以獲取HTML文檔,這讓萬維網(wǎng)真正到來,真正體現(xiàn)了互聯(lián)網(wǎng)的快捷、免費(fèi)思維。
上面提到了TCP/IP,HTTP,F(xiàn)TP都是通信管道,后來大家把注意力轉(zhuǎn)向內(nèi)容。我們感興趣的文件隨著IT技術(shù)的發(fā)展而快速爆發(fā),例如數(shù)據(jù)庫快速發(fā)展導(dǎo)致各種應(yīng)用系統(tǒng)快速發(fā)展。同時(shí),數(shù)據(jù)的更新頻度更加快速,這種即時(shí)信息推動了互聯(lián)網(wǎng)流量快速增長。通過基于HTTP的HTML,最終用戶可以瀏覽位于遠(yuǎn)程服務(wù)器上的文件。
當(dāng)時(shí),遠(yuǎn)程服務(wù)器屬于局域網(wǎng),局域網(wǎng)連接到互聯(lián)網(wǎng)需要專用設(shè)備,可惜的是這種專用設(shè)備并不好用(直到后來路由器和交換機(jī)被思科發(fā)明出來),因此通用網(wǎng)關(guān)接口(CGI)規(guī)范被制定出來,它允許Web服務(wù)器超越文件服務(wù)器并從內(nèi)部數(shù)據(jù)庫中獲取數(shù)據(jù),并動態(tài)更改HTML。
最初,CGI是在1993年由美國國家超級電腦應(yīng)用中心(NCSA)為NCSA HTTPd Web服務(wù)器開發(fā)的,當(dāng)年NCSA內(nèi)部有一份簡單的CGI規(guī)范說明,后來在1997年Ken Coar領(lǐng)導(dǎo)的團(tuán)隊(duì)制定了CGI1.1規(guī)范,并提交RFC。CGI規(guī)范是Web應(yīng)用程序開發(fā)中的一個(gè)重大突破,確保了相同的CGI程序在不同的Web服務(wù)器上工作。
CGI成為傳遞動態(tài)內(nèi)容的最常用手段。只是互聯(lián)網(wǎng)發(fā)展太快了,CGI的性能無法跟上,每個(gè)對CGI腳本的請求都會產(chǎn)生一個(gè)單獨(dú)的進(jìn)程。這種設(shè)計(jì)讓CGI在高峰負(fù)載時(shí)也消耗大量資源。解決方案非常多,功能性和可伸縮性成為關(guān)鍵。
許多CGI替代者都采用服務(wù)器端編程技術(shù)來實(shí)現(xiàn)業(yè)務(wù)邏輯,包括ASP、ColdFusion、PHP和Perl等等,其中至今仍然在大量使用的是PHP ,PHP 繼承自一個(gè)老的工程,名叫 PHP/FI,PHP/FI 在 1995 年由 Rasmus Lerdorf 創(chuàng)建,最初只是一套簡單的 Perl 腳本,用來跟蹤訪問他主頁的人。然后,即使是PHP,最終由于可移植性和面向?qū)ο蟮木幊淘O(shè)計(jì),Java超越了PHP和其他CGI平臺。
Java自1991年誕生以來已經(jīng)走過了很長的一段路,當(dāng)時(shí)Sun公司推出了“綠色計(jì)劃”,試圖集成數(shù)字消費(fèi)設(shè)備,如電視機(jī)、CD播放機(jī)和計(jì)算機(jī)。OAK(名字來自高斯林窗外的一棵橡樹!)誕生了,但直到出現(xiàn)HotJava和小程序,才開始活躍起來。1995年,Sun發(fā)布了開源Java,向微軟發(fā)起了挑戰(zhàn),反響巨大。這促使Java深入到服務(wù)器端開發(fā)領(lǐng)域。
Sun在Java中加入了Internet功能,并在1997年6月發(fā)布了servlet接口。servlet以CGI替代為目標(biāo)。與CGI為每個(gè)請求啟動一個(gè)進(jìn)程不同,servlet使用更細(xì)粒度的線程在單個(gè)進(jìn)程中運(yùn)行。servlet采用了更有效的體系架構(gòu),能夠應(yīng)對互聯(lián)網(wǎng)上的復(fù)雜情況。Java servlet為開發(fā)Java Web組件提供了基礎(chǔ)。servlet優(yōu)點(diǎn)是每個(gè)額外的并發(fā)請求帶來的額外開銷非常小。
servlet技術(shù)需要真正的Java編程技能才能有效應(yīng)用,外觀和良好體驗(yàn)為web應(yīng)用帶來了巨大方便,但是圖像支持還不是那么良好。于是Sun公司在1998年發(fā)布了JavaServer Pages (JSP),這來自于微軟ASP的啟發(fā),也有些人說是復(fù)制的,它使得編寫動態(tài)HTML頁面變得容易。
使用JSP的使用非常簡單,有些工具(例如Dreamweaver)能讓非程序員來構(gòu)建WWW網(wǎng)站前端頁面,當(dāng)然要servlet帶動后端服務(wù)器代碼(例如javabean)才能完成完整的WWW網(wǎng)站構(gòu)建工作,這樣構(gòu)建的WWW網(wǎng)站具有模塊化、可維護(hù)、可伸縮和可移植優(yōu)點(diǎn),從而完成簡單網(wǎng)站到復(fù)雜Web應(yīng)用程序的轉(zhuǎn)變,從而實(shí)現(xiàn)前后端分離。
JSP官方版本1.0和1.1都出現(xiàn)在1999年,都很受歡迎,版本1.2出現(xiàn)于2001年,是目前最流行的實(shí)現(xiàn)。
JSP終究還是含有Java代碼,前后端沒有徹底分離,因此人們在2009年發(fā)明了node-js,這讓前端開發(fā)人員崛起,他們單純使用HTML+CSS+JavaScript前端語言就能完成前端頁面的開發(fā),而不需要使用含有各種后端交互印記的標(biāo)簽。
于是,基于node-js的React、Angela、VUE框架成為潮流。
*請認(rèn)真填寫需求信息,我們會在24小時(shí)內(nèi)與您取得聯(lián)系。