1. 程式人生 > >Java Web基礎(一)(HTML、Servlet/JSP)

Java Web基礎(一)(HTML、Servlet/JSP)

       要成為牛逼的JavaWeb程式設計師, Java Web的基礎非常重要,現在有各種成熟的設計框架例如JQuery、Spring、Struts、Mybatis,將Java Web基礎的複雜且通用的邏輯進行封裝,減少了程式設計師的程式碼量,提高了編碼效率,但是這些框架非常不利於我們瞭解Java Web底層如何運作,甚至不知道HTML(HyperText MarkupLanguage)、HTTP(HyperText Transfer Protocol)、URL(Uniform Resource Locator)以及文字編碼的問題。當我們習慣使用這些框架而不去探究其實現原理時,我們的開發水平也就被這些框架所禁錮了,學不到核心,也就無法創新。

       我就是一個被這些框架所坑的小程式猿。由於學東西很快,所以在專案中很快就能上手,產生勞動力。但是越寫越覺得不安,“為什麼要這樣寫呢?”、“Struts2是怎麼把JSP頁面、Controller、Model聯絡起來的?”、“前臺的請求是如何被後臺準確接收的?”、“Servlet是什麼?”……如果你沒想過這些問題,說明你已經被當前的工作禁錮了思維,僅僅為了實現某個功能而程式設計,幾乎沒有任何技術水平的提高。

       在認識到這些之後,我就開始了Java Web基礎的學習,下面是我的學習筆記,供大家參考。

關於HTML

       這個想必大家都知道是什麼,HTML是以便籤(Tag)的方式定義檔案結構,是構建介面的基礎,被放在伺服器上供客戶端訪問。瀏覽器會根據這些標籤繪製出頁面的樣子。下面這個網站有HTML的教程:

http://www.w3school.com.cn/html/

關於URL、URI、URN

       HTML是被放在伺服器上的,客戶端如何訪問HTML呢?有的人說“通過URL”、“通過URI”,可能說這個的人也不知道啥是URL、URI,下面是這三個縮寫的全拼:

  • URL:Uniform Resource Locator——統一資源定位
  • URI:Uniform Resource Identifier——統一資源標識
  • URN:Uniform Resource Name­——統一資源名稱

       URN代表某個資源獨一無二的名稱,比如我的這臺電腦的URN為“聯想-T450s-CUSTOM-S3-123456789”,標識世界上就這一臺電腦,再比如現在有一臺跟我這個品牌配置相同的電腦可能叫“聯想-T450s-CUSTOM-S3-987654321”。

       URI是一個用於標識某一網際網路資源名稱的字串。 該種標識允許使用者對任何(包括本地和網際網路)的資源通過特定的協議進行互動操作。URL是URI的其中一種使用方式,除此之外,URI還可以用特定的保留字元、不同的編碼指定需要訪問的資源,例如給某人發郵件,可以構建一個這樣的URI:mailto:[email protected]

動態網頁、靜態網頁

       靜態網頁就是純HTML的,裡面的內容不會隨著時空變化的網頁。

       動態網頁就是可以根據客戶端的請求的引數、時空不同,讓網頁在不同客戶端上看到的內容有是不同的。(這是最傻瓜式的解釋)

       動態網頁是如何動的呢?是伺服器根據客戶端的請求引數等資訊,通過執行程式的方式來產生響應內容,然後把內容返回給客戶端,因為執行的程式是百變的,所以產生的響應內容也是千變萬化的。

       這種伺服器上的執行程式有哪些呢?目前處理動態網頁的技術有CGI、PHP、ASP、Servlet/JSP。

       大家注意到Servlet/JSP是寫在一起的,這說明這倆是一個東西,通過後面的知識你就能知道為什麼了。

Servlet/JSP簡介

       終於說道Servlet/JSP了,什麼是Servlet?什麼是JSP?

       我們知道Java程式是一個個.class檔案構成的,這些.class檔案被執行在JVM——Java虛擬機器中,所以在編寫java程式碼時,我們知道我們寫的這些程式碼最終能夠被JVM解析、使用,有時候還需要考慮JVM如何管理Java程式中的物件。

       做一個類比:Servlet/JSP執行在HTTP伺服器上,而包含有Web容器的伺服器才叫做HTTP伺服器,所以Servlet/JSP實際執行在Web容器中,它是客戶端與Servlet/JSP之間通訊的橋樑。我們寫的Servlet/JSP最終能夠被Web容器解析、使用,有時候還需要考慮JVM如何管理Servlet/JSP中的各種物件。

       重要概念:Web容器

       Web容器就是定義了一大堆規範、標準,只要按照這些規範/標準來寫,它就能實現特定的功能(產生靜態/動態網頁,實現各種效果,完成客戶端和HTTP伺服器之間的通訊等)。而Servlet/JSP就是其中一項實現這一大堆規範和標準的技術。

那麼Web容器是如何處理請求/響應的呢?下面是一個例子:

  1. 瀏覽器對Web伺服器發出HTTP請求(例如訪問一個網址)
  2.  HTTP伺服器收到了HTTP請求,將請求交給Web容器處理,容器解析HTTP請求的一些資訊,建立各種物件(如HttpServletRequest、HttpServletResponse、HttpSession等)
  3. 容器根據請求的URL,將下一步處理交給指定的Servlet
  4. Servlet根據已經封裝好的請求物件(HttpServletRequest)的資訊決定如何處理,然後通過相應物件(HttpServletResponse)來建立響應(關鍵的一步,開發人員可以編寫各種業務邏輯)
  5. Web容器通知HTTP伺服器“響應已經建立好,並轉換為HTTP響應”,並將響應傳回瀏覽器。

       Servlet與JSP的關係

       終於講到正題了,你可能急切的想用HTML寫一個JSP頁面看一下效果,但其實JSP不只是用HTML寫的,所有的JSP頁面,最終都會被web容器編譯成“.class”檔案,然後載入到容器之中。為什麼是“.class”檔案呢?因為web容器會將JSP頁面首先轉譯為“.java”檔案。這個“.java”檔案通過直接或間接(直接或間接的原因,馬上就能看到)的繼承HttpServlet,使得這個“.java”檔案成為了一個Servlet,所以不管是Servlet還是JSP頁面,最終提供服務的還是Servlet例項。要掌握JSP,必須首先對Servlet有一定的瞭解。我們先來看看一個Servlet是怎麼寫的,上程式碼!

<span style="font-family:Microsoft YaHei;font-size:14px;">package com.web;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class SimpleServlet extends HttpServlet {
	@Override
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
		out.println("<HTML>");
		out.println("  <HEAD><TITLE>A Servlet</TITLE></HEAD>");
		out.println("  <BODY>");
		out.print("    This is ");
		out.print(this.getClass());
		out.println(", using the GET method, " + new java.util.Date());
		out.println("  </BODY>");
		out.println("</HTML>");
		out.flush();
		out.close();
	}
}
</span>

       通過上面的程式,我們注意到:首先Servlet類必須繼承自HttpServlt(直接繼承);然後如果要輸出HTML,必須通過java的輸入/輸出功能,並且可以通過java程式碼生成動態的HTML內容(例如上面的日期)。

       接下來再看一個可以達到同樣效果的JSP頁面長啥樣:

<span style="font-family:Microsoft YaHei;font-size:14px;"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>A Servlet</title>
  </head>
  <body>
  	<h1><%= new java.util.Date() %></h1>
  </body>
</html>
</span>

       以上兩段程式碼能達到同樣的效果,但是用JSP書寫起來更為簡單。Servlet是通過java程式碼實現頁面的輸出和邏輯的處理,JSP是通過HTML中填充java程式碼實現介面的輸出和邏輯的處理。那JSP是如何實現Servlet同樣功能的呢?它底層的操作原理是啥?

       首先我們把專案釋出在Tomcat(web容器)中並啟動Tomcat,然後訪問以下這個JSP頁面,接下來到Tomcat的根目錄,找到work/Catalina/localhost目錄並進入,找到你釋出的工程目錄並進入,在裡面你會發現,你寫的JSP頁面被編譯為xxx_jsp.class、xxx_jsp.java,xxx是你的JSP頁面的名字,我們開啟xxx_jsp.java:

          

       看到了吧,這就是web容器給我們做的工作:它把JSP頁面轉譯為了“.java”檔案,這個java檔案繼承了HttpJspBase,而HttpJspBase繼承自HttpServlet(所以說是間接繼承),而HTML的輸出方式與之前是一樣的。

       綜上所述,Servlet和JSP其實是一體兩面的東西,知道了這一點,對於我們以後的程式設計生涯會有很大的幫助,至少在我們遇到問題時,可以多一層思路解決。

       MVC/Model 2的概念

       講到這裡,雖然Web框架都建立在我們的Servlet/JSP基礎之上,但我覺得還有一點非常重要的基礎知識,那就是MVC和Model 2的概念。它是絕大部分Web框架的基礎,萬變不離其宗,瞭解MVC和Model 2之後,能讓我們更進一步的認識一個web框架的實現原理。

       從上面的程式中你可能注意到一個特別彆扭的地方(如果你的碼感強的話),那就是不管是Servlet還是JSP,都會把java程式碼和html混合在一起,這是非常不好的,一方面程式碼不容易理解,另一方面不容易維護,對於日後團隊合作也是非常大的困擾。

       針對這個問題,不知道是哪位大神級的前輩,通過改造MVC模式,創造了適合web使用的Model2模型。

       我們首先來了解一下啥是MVC, MVC 是 Model、View、Controller的縮寫,通常譯作模型、檢視、控制器。最早MVC模型是為實現桌面應用程式中資料的不同展現方式和更新設計的,關於MVC的詳細介紹請點選這裡,我們在這裡只需要關心一下幾點:

  • 模型不會有畫面相關的程式程式碼
  • 檢視負責畫面相關的邏輯
  • 控制器知道某個操作必須呼叫哪些模型
  • 模型被更新後,可以通知檢視做下一步操作——查詢模型狀態

       有人認為,MVC這樣的職責分配,可以套用在web應用上:

  • 檢視部分可以由網頁來實現
  • 伺服器上的資料訪問和業務邏輯可以由模型來負責
  • 控制器接收到瀏覽器的請求,決定呼叫哪些模型來處理,並把處理結果返回給瀏覽器

       然而這裡有一個非常重要的流程走不通,那就是上面加粗標黃的第四點:模型被更新後,無法直接通知檢視下一步該如何操作。造成這個的原因是web是基於HTTP的,必須基於請求/響應模型,沒有請求就不會有響應,伺服器也就無法“主動滴”通知瀏覽器做檢視的改變。

       基於這個問題,我們大神級的前輩提出了一個名為Model 2的解決方案,它的互動示意圖如下:

       

       這裡我就不詳細說了,仔細看上面的就能發現,Model 2是在MVC的基礎上,HTTP請求攔截,然後控制器先從模型那裡獲取模型狀態,然後通知檢視查詢模型狀態,最後把檢視返回給HTTP響應。理解了這個以後,你就能明白為什麼我們訪問一個網站的時候會有一個載入過程了,因為HTTP請求到響應的這段時間,伺服器做了好多事情呀!

所謂設計模式的目的就是將變化的和不變的分離開,使用MVC使專案結構清晰了很多,搞起來似乎也更容易理解了。

       Java EE

       最後放一個可能很多人都不知道但是也挺重要的知識吧。

       Java 代表了一個開放的平臺,根據領域,劃分為Java SE(Java Platform,Standard Edition)、Java ME(Java Platform,Micro Edition)、Java EE(Java Platform,Enterprise Edition)。

       Java SE書初學Java的基礎版本,解決標準桌面應用程式需求。Java ME面向微型裝置手機PDA啥的。Java EE就牛逼多了,可以全面性解決各個領域的問題,Servlet/JSP就屬於Java EE。