說明:本筆記僅是書上的筆記太惠。實驗室某個項目學習使用磨淌。
單身狗的世界,程序猿的世界垛叨,這又是狗又是猿的伦糯,我柜某。。敛纲。
記筆記記筆記
原文地址
1.1 Web開發(fā)中的請求——響應模型:
在Web中喂击,具體步驟如下:
1、Web瀏覽器(如IE)發(fā)送請求淤翔,如訪問http://sishuk.com翰绊。
2、Web服務器(如Tomcat)接收請求旁壮,處理請求(比如用戶新增监嗜,則把用戶保存一下),最后產生響應(一般為html)抡谐。
3裁奇、Web服務器處理完成后,返回內容給web客戶端(一般就是我們的瀏覽器)麦撵,客戶端對接收的內容進行處理(如web瀏覽器會將接收的html內容進行渲染展示給用戶)刽肠。
所以,在web中都是Web客戶端發(fā)起請求免胃,Web服務器接收音五、處理并產生響應。一般的web服務器不能主動通知Web客戶端更新內容羔沙。但是HTML5 websocket可以實現(xiàn)服務器主動通知Web客戶端躺涝。
1.2 標準MVC模型概述
MVC模型:是一種架構型的模式,本身不能引入新功能扼雏,只是幫助我們將開發(fā)的結構組織的更加合理坚嗜,使展示與模型分離、流程控制邏輯呢蛤、業(yè)務邏輯調用與展示邏輯分離惶傻。
首先讓我們了解下MVC(Model—View—Controller)三元組的概念:
Model(模型):數(shù)據(jù)模型,提供要展示的數(shù)據(jù)其障,因此包含數(shù)據(jù)和行為银室,可以認為是領域模型或JavaBean組件(包含數(shù)據(jù)和行為),不過一般現(xiàn)在都分離開來:Value Object(數(shù)據(jù))和服務層(行為)励翼。也就是模型提供了模型數(shù)據(jù)查詢和模型數(shù)據(jù)狀態(tài)更新等功能蜈敢,包含數(shù)據(jù)和業(yè)務。
View(視圖):負責進行模型的展示汽抚,一般就是我們見到的用戶界面抓狭,客戶想要看到的東西。
Controller(控制器):接收用戶請求造烁,委托給模型進行處理(狀態(tài)改變)否过,處理完畢后把返回的數(shù)據(jù)模型返回給視圖午笛,由視圖負責進行展示。也就是說控制器做了一個調度員的工作苗桂。
在標準的MVC模型中能主動推送視圖進行更新(觀察者設計模式药磺,在模型上注冊視圖,當模型更新時自動更新視圖)煤伟,但在Web開發(fā)中模型是無法主動退給視圖(無法主動更新用戶界面)癌佩,因為在Web開發(fā)是請求—響應模式。
1.3 Web MVC概述
模型—視圖—控制器概念和標準MVC模型一樣便锨,接下來我們看看Web MVC模型架構围辙,如下圖。
在Web MVC模式下放案,模型無法主動推送數(shù)據(jù)給視圖姚建,如果用戶想要視圖更新,需要再發(fā)送一次請求(即請求—響應模式)卿叽。
1.4Web端開發(fā)發(fā)展歷程
核心歷程:
1.4.1 CGI
CGI:(Common Gateway Interface)公共網關接口桥胞,一種在Web服務器端使用的腳本技術恳守,使C或Perl語言編寫考婴,用于接收Web用戶請求并處理,最后動態(tài)產生響應給用戶催烘,但每次請求將產生一個進程沥阱,重量級。
1.4.2 Servlet
Servlet:一種JavaEE web組件技術伊群,是一種在服務器端執(zhí)行的組件考杉,用戶接收web用戶請求并處理,最后動態(tài)產生響應給用戶舰始。但每次請求只產生一個線程(而且有線程池)崇棠,輕量級。而且能利用很多的JavaEE技術(如JDBC等)丸卷。本質就是在java代碼里面輸出html流枕稀。但表現(xiàn)邏輯、控制邏輯谜嫉、業(yè)務邏輯調用混雜萎坷,如以下代碼。
public class LoginServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);//為了簡單沐兰,直接委托給dopost處理
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
/*
* 1.邏輯控制:根據(jù)請求參數(shù)選擇要執(zhí)行的功能方法
*/
String submitFlag = request.getParameter("submitFlag");
if("toLogin".equals(submitFlag)) {
toLogin(request,response);
return ;
} else if("login".equals(submitFlag)) {
login(request,response);
return ;
}
toLogin(request, response);//默認到登錄頁面
}
private void toLogin(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
String loginPath = request.getContextPath() + "/ServletLogin";
PrintWriter out = response.getWriter();
/*
* 2.表現(xiàn)代碼:頁面展示直接放在我們的Servlet里面
*/
out.write("<from action='"+loginPath+"' method='post'>");
out.write("<input type='text' name='submitlogin' value='login'/>");
out.write("username:<input type='text' name='username'/>");
out.write("password:<input type='password' name='password'/>");
out.write("<input type='submit' value='login'/>");
out.write("</from>");
}
private void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
//1哆档、收集參數(shù)
String username = request.getParameter("username");
String password = request.getParameter("password");
//2、驗證并封裝參數(shù)(重復的步驟)
/*
* 3.調用業(yè)務對象(javabean)進行登錄住闯,即模型瓜浸,不僅包含數(shù)據(jù)澳淑,還包含處理行為
*/
UserBean user = new UserBean();
user.setUsername(username);
user.setPassword(password);
if(user.login()) {
response.getWriter().write("login success");
} else {
response.getWriter().write("login fail");
}
}
}
這種方法是絕對不可取的,控制邏輯插佛、表現(xiàn)代碼偶惠、業(yè)務邏輯對象調用混雜在一起,最大的問題值直接在Java代碼中輸出Html朗涩,這樣前端開發(fā)人員無法進行頁面風格的修改和設計忽孽,即使修改也很麻煩,因此實際項目中這種做法不可取谢床。
1.4.3 JSP
JSP(Java Server Page):一種在服務器端執(zhí)行的web組件兄一,是一種運行在標準的HTML頁面中嵌入腳本語言(現(xiàn)在只支持Java)的模板頁面技術。本質就是在html代碼中嵌入Java代碼识腿。最終還是會被編譯為Servlet出革,只不過純Servlet開發(fā)頁面簡單、方便渡讼。但是表現(xiàn)邏輯骂束、業(yè)務邏輯、控制邏輯調用還是很混雜成箫。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="com.demo.UserBean"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>登錄</title>
</head>
<body>
<%
String submintFlag = request.getParameter("submitFlag");
if ("login".equals(submintFlag)) {
String username = request.getParameter("username");
String password = request.getParameter("password");
UserBean user = new UserBean();
user.setUsername(username);
user.setPassword(password);
if (user.login()) {
out.write("login success");
} else {
out.write("login fail");
}
} else {
%>
<form action="" method="post">
<input type="hidden" name="submitFlag" value="login">
username:<input type="text" name="username"/><br>
password:<input type="password" name="password"/><br>
<input type="submit" value="login">
</form>
<%
}
%>
</body>
</html>
這種做法也是絕對不可取的展箱,控制邏輯、業(yè)務邏輯蹬昌、表現(xiàn)代碼對象調用混雜在一起混驰,但比直接在Servlet里面輸出html要好一點,前端開發(fā)人員可以進行簡單的頁面風格等的設計與修改(但如果嵌入的Java腳本太多也很難修改)皂贩,因此這種做法也不可取的栖榨。
JSP本質上還是Servlet,最終在運行時會生成一個Servlet明刷,但這使得寫html簡單點婴栽,但是仍然是控制邏輯、業(yè)務邏輯辈末、頁面代碼混雜在一起的愚争。
1.4.4 Model1
Model1:可以認為是JSP的增強版,可以認為是jsp+javabean
特點:使用<jsp:userBean>標準動作本冲,自動將參數(shù)封裝為javabean組件准脂;還是必須使用java腳本執(zhí)行邏輯代碼。
Model1架構:
Model1架構中檬洞, JSP負責控制邏輯狸膏、表現(xiàn)邏輯、業(yè)務對象(javabean)的調用添怔,只是比純JSP簡化了獲取請求參數(shù)和封裝請求參數(shù)湾戳。同樣是不好的贤旷,在項目中應該禁用。
1.4.5 Model2
Model2:在JavaEE世界里砾脑,它可以認為就是Web MVC模型
Model2架構其實可以認為就是我們所說的Web MVC模型幼驶,只是控制器采用的Servlet、模型采用JavaBean韧衣、視圖采用JSP盅藻,如下圖。
從Model2架構可以看出畅铭,視圖和模型分離了氏淑,控制邏輯與展示邏輯分離了
缺點:
控制器:
1、控制邏輯可能比較復雜硕噩,每個模塊基本需要一個控制器假残,造成控制邏輯可能很復雜。
2炉擅、請求參數(shù)到模型的封裝可能比較麻煩辉懒,如果交給框架來做這件事情,就得到了解放谍失。
3眶俩、選擇下一個視圖,嚴重也來ServletAPI袱贮,這樣很難或基本不可能更換視圖仿便。
4、給視圖傳輸要展示的模型數(shù)據(jù)攒巍,使用ServletAPI,更換視圖技術要一個更換荒勇,很麻煩柒莉。
模型:
1、此處模型使用JavaBean沽翔,可能造成JavaBean組件類很龐大兢孝,一般現(xiàn)在項目都是采用三層結構,而不采用JavaBean仅偎。
視圖:
1跨蟹、現(xiàn)在被綁定JSP,很難更換視圖橘沥,比如Velocity窗轩、FreeMarker;比如我要支持Excel座咆、PDF視圖等痢艺。
1.4.6 服務到工作者
服務到工作者:Front Controller + Application Controller + Page Controller + Context仓洼。即前段控制器+應用控制器+頁面控制器+上下文,也是Web MVC堤舒,只是職責更加明確色建,如下圖:
職責:
Front Controller:前端控制器,負責為表現(xiàn)層提供統(tǒng)一訪問點舌缤,從而避免Model2中出現(xiàn)的重復的控制邏輯箕戳;并且可以為多個請求提供公用的邏輯,將選擇視圖和具體功能處理分離国撵。
Application Controller:應用控制器漂羊,前端控制器分離選擇具體視圖和具體的功能處理之后,需要有人來管理卸留,應用控制器就是用來選擇具體視圖技術(視圖的管理)和具體功能處理(頁面控制器/命令對象/動作管理)走越,一種策略設計模式的應用,可以很容易的切換視圖/頁面控制器耻瑟,互不產生影響旨指。
Page Controller:頁面控制器/動作/處理器:功能處理代碼、收集參數(shù)喳整、封裝參數(shù)到模型谆构,轉調業(yè)務對象處理模型,返回邏輯視圖交給前端控制器(和具體視圖解耦)框都,由前端控制器委托給應用控制器選擇具體的視圖來展示搬素,可以是命令設計模式的實現(xiàn)。頁面控制器也被稱為處理器或動作魏保。
Context:上下文熬尺,有了上下文之后,我們可以將相關數(shù)據(jù)放置在上下文谓罗,從而與協(xié)議無關(如ServletAPI)的訪問/設置模型數(shù)據(jù)粱哼,一般通過ThreadLocal模式實現(xiàn)。
目的:
干凈的web表現(xiàn)層:
模型和視圖的分離檩咱;
控制器中邏輯控制和功能處理分離(收集并封裝參數(shù)到模型對象揭措、業(yè)務對象的調用);
控制器中視圖選擇與具體視圖技術分離刻蚯。
輕薄的web表現(xiàn)層:
做的事情越少越好绊含,薄薄的,不應該包含無關代碼炊汹;
只負責收集并組織參數(shù)到模型對象躬充,啟動業(yè)務對象的調用;
控制器只返回邏輯視圖名由相應的應用控制器來選擇具體使用的視圖策略;
盡量少使用框架特定API麻裳,保證容易測試口蝠。