Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 久久精品成人免费看,亚洲欧洲一区二区三区,综合国产在线

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          我的Java Web之路11 - 初識(shí)HTML

          本系列文章旨在記錄和總結(jié)自己在Java Web開發(fā)之路上的知識(shí)點(diǎn)、經(jīng)驗(yàn)、問題和思考,原來已經(jīng)分享在我的CSDN博客,現(xiàn)在分享在頭條,希望能幫助更多碼農(nóng)和想成為碼農(nóng)的人。版權(quán)聲明:本文為CSDN博主「普通的碼農(nóng)」的原創(chuàng)文章,遵循CC 4.0 by-sa版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/liyongyan1202/article/details/89064944
          

          1. 介紹
          2. 核心思想
          3. 基本結(jié)構(gòu)
          4. 文本信息
          5. 鏈接
          6. 表單
          7. 總結(jié)

          介紹

          前面的文章多次使用到了HTML(HyperText Markup Language,中文就是超文本標(biāo)記語言)。這門語言可以使用任何的文本編輯器進(jìn)行編寫,寫出的文檔就是網(wǎng)頁,只要將文件名以后綴 .html 結(jié)尾,瀏覽器就可以解釋該文檔,并以一定的格式呈現(xiàn)出來。

          HTML是Web前端三劍客之一,主要是負(fù)責(zé)數(shù)據(jù)的結(jié)構(gòu)、框架或骨架,表示哪些數(shù)據(jù)是標(biāo)題啊、主體啊、導(dǎo)航啊、鏈接啊、表格啊、段落啊、圖片啊、音頻、代碼啊等。簡(jiǎn)而言之,就是表示數(shù)據(jù)是什么。

          核心思想

          HTML的核心思想很簡(jiǎn)單,就是給你的信息打標(biāo)記,舉個(gè)例子:

          <這是一篇文章>
          	<這是標(biāo)題>XX爆炸性新聞</這是標(biāo)題>
          	<這是段落>
          		某年某月某日,某某發(fā)生某事。。。
          	</這是段落>
          	<這是段落>
          		其他事情。。。
          	</這是段落>
          </這是一篇文章>
          

          尖括號(hào) < > 及其里面的詞就是標(biāo)記或者標(biāo)簽,只不過HTML標(biāo)準(zhǔn)里面用的是英文單詞,我這只是用中文的詞來說明這個(gè)思想。

          標(biāo)記有開始標(biāo)記結(jié)束標(biāo)記,結(jié)束標(biāo)記里面多一個(gè)正斜杠,就是 </ > 。

          真正的信息(就是要呈現(xiàn)給用戶看的)就寫在開始標(biāo)記和結(jié)束標(biāo)記之間,這就是標(biāo)記的內(nèi)容。有時(shí)候沒有內(nèi)容,開始標(biāo)記和結(jié)束標(biāo)記可以合二為一,變成 < /> ,就是把正斜杠寫到右尖括號(hào)前面,或者省略正斜杠。

          標(biāo)記及其內(nèi)容合起來叫做元素,比如例子中的開始標(biāo)記<文章>和結(jié)束標(biāo)記</文章>及其之間的內(nèi)容就是一個(gè)元素。可以看到元素可以嵌套,就是元素里面的內(nèi)容可以再次包含元素,不過開始標(biāo)記和結(jié)束標(biāo)記要注意遙相呼應(yīng),事實(shí)上,編寫的時(shí)候可以采用縮進(jìn)來增加層次感且不易出錯(cuò)。

          元素還有屬性,屬性可以有屬性值,也可以沒有,這些后面再討論。這里要提到的是一個(gè)編寫規(guī)范,不管是標(biāo)記、屬性還是值,習(xí)慣上都采用英文小寫單詞用連字符(就是短橫線、減號(hào))相連。表單中的需要發(fā)往Web服務(wù)器的數(shù)據(jù)可以使用后端的開發(fā)規(guī)范。

          每一個(gè)元素都可以設(shè)置一個(gè)id屬性,其值必須在該網(wǎng)頁中是唯一的。

          目前HTML的版本是HTML5,大多數(shù)瀏覽器版本都支持大部分常用的特性。再次強(qiáng)調(diào),HTML的主要思想就是給你的信息打標(biāo)記,這些標(biāo)記表示數(shù)據(jù)的結(jié)構(gòu)、框架或骨架,就是語義,至于數(shù)據(jù)如何呈現(xiàn)(比如呈現(xiàn)在哪個(gè)位置,什么顏色、字體、背景等等)和動(dòng)態(tài)行為是由CSS(層疊樣式表,Cascading Style Sheets)和JavaScript來負(fù)責(zé)。它們都由瀏覽器來解釋執(zhí)行。

          基本結(jié)構(gòu)

          HTML5的網(wǎng)頁基本都有如下結(jié)構(gòu):

          <!DOCTYPE html>
          <html lang="zh-cmn-hans">
          <head>
          	<meta charset="utf-8" />
          	<title>這里是網(wǎng)頁的標(biāo)題</title>
          </head>
          <body>
          </body>
          </html>
          

          可以看到,基本結(jié)構(gòu)就是由各種標(biāo)記組成的,只不過標(biāo)記使用的是英文單詞,而且這些標(biāo)記都是標(biāo)準(zhǔn)化(這樣各家瀏覽器都能識(shí)別)了的,瀏覽器必須識(shí)別它們。這些標(biāo)記也很語義化(這樣人類能容易識(shí)別,便于開發(fā)和維護(hù)網(wǎng)頁),基本上都是使用語義相對(duì)應(yīng)的英文單詞或縮寫,這也是理所當(dāng)然的,便于記憶和使用嘛。

          基本結(jié)構(gòu)里面包含以下幾點(diǎn):

          • 第一行的DOCTYPE聲明了本網(wǎng)頁是HTML5網(wǎng)頁,根據(jù)HTML網(wǎng)頁的編寫規(guī)范,基本上這個(gè)詞是網(wǎng)頁文檔中唯一的大寫單詞;
          • <html>元素:所有信息都包含在這個(gè)元素里面,沒什么可說的,不過該元素有一個(gè)屬性lang,在這個(gè)網(wǎng)頁中,我把它的值設(shè)置為zh-cmn-hans,就是說本網(wǎng)頁的語言是是簡(jiǎn)體中文,關(guān)于語言的編碼,也是相當(dāng)復(fù)雜,有專門的標(biāo)準(zhǔn),這里暫且不說;
          • <head>元素:它必須是<html>元素里面的第一個(gè)元素。它里面的信息除了下面的<title>元素之外,在瀏覽器上都是不可見的,就是說用戶在瀏覽器上不能直接看到里面的信息;
          • <body>元素:先說這個(gè)元素,這是<html>元素里面的第二個(gè)元素。你可以在這個(gè)元素里面放置你的信息,包括文本、圖像、音頻、視頻等,當(dāng)然你又可以給這些信息打上合適的標(biāo)記;
          • <meta>元素:它被包含在<title>元素里面,而且它由于沒有內(nèi)容,所以開始標(biāo)記和結(jié)束標(biāo)記可以合二為一。它有一個(gè)屬性charset,非常重要,就是指示瀏覽器使用哪種字符編碼(簡(jiǎn)單的理解就是編碼規(guī)定了如何將二進(jìn)制數(shù)據(jù)映射到我們?nèi)祟惪勺R(shí)別的文字和符號(hào),簡(jiǎn)稱字符,因?yàn)橛?jì)算機(jī)只能識(shí)別0、1的二進(jìn)制數(shù)據(jù))來讀取本文檔。

          但是,僅僅告訴瀏覽器使用何種字符編碼還不行,網(wǎng)頁文檔本身在使用文本編輯器編寫完保存的時(shí)候,必須使用該字符編碼來保存;通過網(wǎng)絡(luò)傳輸?shù)脑挘莻鬏敃r(shí)也必須使用該字符編碼來傳輸。

          就好像我給你寫了一封信,信上指示你說要用英語來讀這封信,但信的內(nèi)容卻是用中文寫的,那么你還是不能讀這封信。這里我使用了普遍采用的utf-8這種字符編碼,Web上基本都用這個(gè),它能表示全球各個(gè)語言中的字符,而且占用字節(jié)數(shù)較少。字符編碼也是比較復(fù)雜但很重要的內(nèi)容,這里暫且不說;

          • <title>元素:它的內(nèi)容將顯示在瀏覽器上,如下圖:

          OK,每個(gè)網(wǎng)頁都有這個(gè)基本結(jié)構(gòu),剩下的就是往<body>元素里面添加你的各種信息了。

          文本信息

          首先,我們可以向<body>元素里面添加文本,畢竟文字在我們的生活中占據(jù)很重要的位置,特別是在古代。文字可以寫成小說、劇本、新聞、資訊等等。添加文本很簡(jiǎn)單,直接在元素里面敲文字(各種語言都行)就可以了。

          如果光是這樣的話,那就談不上說HTML負(fù)責(zé)數(shù)據(jù)的結(jié)構(gòu)、框架或骨架了。不錯(cuò),HTML還提供了很多標(biāo)記來描述數(shù)據(jù),這里先說一些常用的。

          寫文章的時(shí)候通常要為文章起標(biāo)題,而且有文章的總標(biāo)題,副標(biāo)題,文章內(nèi)容相關(guān)的放在同一個(gè)標(biāo)題下,標(biāo)題下又可能有若干個(gè)子標(biāo)題,就類似文檔的大綱似的。所以,HTML提供了<h1>、<h2>、<h3>、<h4>、<h5>、<h6>這六個(gè)標(biāo)記來說明標(biāo)題的語義。我們?cè)囋嚱o信息打上這些標(biāo)記會(huì)是什么樣子,先看代碼:

          <!DOCTYPE html>
          <html lang="zh-cmn-hans">
          <head>
          	<meta charset="utf-8" />
          	<title>這里是網(wǎng)頁的標(biāo)題</title>
          </head>
          <body>
          	<h1>這是一級(jí)標(biāo)題</h1><h2>這是一級(jí)標(biāo)題</h2>
          	<h3>這是一級(jí)標(biāo)題</h3><h4>這是一級(jí)標(biāo)題</h4>
          	<h5>這是一級(jí)標(biāo)題</h5><h6>這是一級(jí)標(biāo)題</h6>
          </body>
          </html>
          

          我特地把這些信息兩個(gè)一行來寫,看看瀏覽器是怎么處理的:

          可以看到,瀏覽器會(huì)把各級(jí)標(biāo)題的字體大小顯示的不太一樣,一級(jí)標(biāo)題最大,六級(jí)標(biāo)題最小。大多數(shù)瀏覽器都會(huì)這么處理。

          那么問題來了,不是說HTML只負(fù)責(zé)信息的語義,不負(fù)責(zé)信息是如何展示的嗎?話雖如此,給不同語義的信息來個(gè)默認(rèn)的展示效果,不就省的我們還要再寫信息如何展示的代碼了嘛。這又再一次體現(xiàn)了契約優(yōu)先(本質(zhì)就是由默認(rèn)值)的思想。這就是說我們還是可以修改這些各級(jí)標(biāo)題是如何展示的,比如字體、顏色等等,這就要用到CSS了。

          注意,瀏覽器可以關(guān)閉CSS和JavaScript,就是讓這兩個(gè)技術(shù)不起作用,從這個(gè)角度看,給標(biāo)記設(shè)置默認(rèn)的展示效果也有這方面的原因。

          雖然標(biāo)記有默認(rèn)的展示效果,但我們一定不能為了獲得這些類似的展示效果而強(qiáng)行給某些信息打上標(biāo)記,而是應(yīng)該使用CSS去獲得這些展示效果。比如,不能為了加大字體就強(qiáng)行把不是標(biāo)題的內(nèi)容打上<h1>標(biāo)記,這應(yīng)該交給CSS去做,是否打上<hn>標(biāo)記(n代表1、2、3、4、5、6)應(yīng)該考慮該內(nèi)容在語義上是否是標(biāo)題!

          第二點(diǎn)很重要的是,明明代碼里面兩個(gè)標(biāo)題一行,為何瀏覽器展示的效果確是每個(gè)標(biāo)題占一行?

          這是因?yàn)镠TML規(guī)定了某些標(biāo)記有個(gè)作用,瀏覽器遇到它就必須另起一行來展示,有這個(gè)作用的標(biāo)記就叫塊級(jí)標(biāo)記,沒有這個(gè)作用的就是行級(jí)標(biāo)記(不知道是否可以這么劃分,通常的劃分方式是塊級(jí)標(biāo)記是里面可以嵌套其他標(biāo)記的,行級(jí)標(biāo)記是里面不可以嵌套其他標(biāo)記的)。

          事實(shí)上,HTML規(guī)定文本里面的格式(縮進(jìn)、換行、多個(gè)連續(xù)的空格等等)都沒用,瀏覽器會(huì)把這些格式壓縮成一個(gè)空格。比如下面的代碼實(shí)際展示的是一行:

          <body>
          	這是第一段。。。
          	這是第二段。。。
          	這是第三段。。。
          </body>
          

          展示效果成了:

          這是第一段。。。 這是第二段。。。 這是第三段。。。 
          

          除了表示標(biāo)題的標(biāo)記以外,還有其他很多作用于文本,甚至是整個(gè)語義上的布局的標(biāo)記,下面僅僅使用一段代碼來展示比較常用的標(biāo)記,不做過多解釋說明。

          <!DOCTYPE html>
          <html lang="zh-cmn-hans">
          <head>
          	<meta charset="utf-8" />
          	<title>這里是網(wǎng)頁的標(biāo)題</title>
          </head>
          <body>
          	<header>
          		<h1>這里是網(wǎng)頁的頁眉,里面可以有導(dǎo)航</h1>
          		<nav>
          			這里是整個(gè)頁面的導(dǎo)航按鈕。。。
          		</nav>
          	</header>
          	<main><!-- 一個(gè)頁面往往只有一個(gè)主體部分 -->
          		<article><!-- 這里也可以使用通用容器標(biāo)記<div> -->
          			<header>
          				<h2>這里是主體的頁眉,可以有主體的導(dǎo)航/目錄、介紹等等</h2>
          				<nav>
          					這里是目錄
          				</nav>
          				<p>這里是介紹</p>
          			</header>
          			<article>
          				<h2>這里是第一篇文章</h2>
          				<p>這里是段落一</p>
          				<p>這里是段落二</p>
          				<p>。。。</p>
          			</article>
          			<article>
          				<h2>這里是第二篇文章</h2>
          				<section>
          					<h3>這里是第二篇文章的第一部分</h3>
          					<p>與上面類似</p>
          				</section>
          				<section>
          					<h3>這里是第二篇文章的第二部分</h3>
          					<p>與上面類似</p>
          				</section>
          			</article>
          		</article>
          	</main>
          	<aside>
          		<h2>這里是附注,往往跟主體內(nèi)容相關(guān)性沒那么強(qiáng),但比較獨(dú)立,瀏覽器上通常會(huì)顯示主體的兩側(cè)</h2>
          	</aside>
          	<footer>
          		<p>這里是整個(gè)頁面的頁腳,通常放一些版權(quán)聲明、隱私政策之類的。</p>
          	</footer>
          </body>
          </html>
          

          涉及到布局的標(biāo)記有:

          • <header>:頁眉
          • <main>:主體
          • <footer>:頁腳
          • <aside>:附注

          涉及到文本內(nèi)容的標(biāo)記有:

          • <nav>:導(dǎo)航
          • <h1>、…、<h6>:標(biāo)題
          • <article>:文章
          • <section>:區(qū)塊,里面的內(nèi)容通常有相似主題。
          • <p>:段落
          • <div>:通用語義,實(shí)在想不出什么語義,那就用它。

          還有很多用來標(biāo)記文本的,比如表示重要性的<strong>、表示強(qiáng)調(diào)的<em>、表示的<figure>和<figcaption>、表示引用或參考的<cite>、表示引述文本的<blockquote>和<q>、表示代碼的<code>等等。

          以上這些標(biāo)記在我們的Java Web開發(fā)中暫時(shí)用不到,所以都不討論。

          鏈接

          鏈接可以說是網(wǎng)頁的靈魂,正是它才能形成Web。表示信息是一個(gè)鏈接的標(biāo)記是<a>。下面舉例:

          <!DOCTYPE html>
          <html lang="zh-cmn-hans">
          <head>
          <meta charset="utf-8" />
          <title>這里是網(wǎng)頁的標(biāo)題</title>
          </head>
          <body>
          	<nav>
          		<ul>
          			<li><a >CSDN</a></li>
          			<li><a >百度</a></li>
          		</ul>
          	</nav>
          	<p>
          		這里是某些文本。。。有些<a href="dir/file.html">東西</a>需要人們?cè)诹硪粋€(gè)網(wǎng)頁中查看
          	</p>
          	<nav>
          		<ul>
          			<li><a href="#question1">What is HTML?</a></li>
          			<li><a href="#question2">How does HTML work?</a></li>
          		</ul>
          	</nav>
          	<article>
          		<h1 id="question1">What is HTML?</h1>
          		<p>
          			HTML is ... <br /><br /><br /><br /><br /><br /><br /><br /><br />
          			<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
          		</p>
          		
          		<h2 id="question2">How does HTML work?</h2>
          		<p>
          			HTML is explained by browser ...
          		</p>
          	</article>
          	<p></p>
          </body>
          </html>
          

          在瀏覽器上呈現(xiàn)這樣:

          上面的例子中<ul>標(biāo)記表示是一個(gè)無序列表,<li>表示是列表中的一項(xiàng)。我們將CSDN、百度和東西打上<a>標(biāo)記,表示它們都是一個(gè)鏈接,用鼠標(biāo)點(diǎn)擊它們可以看到指定的另一個(gè)網(wǎng)頁。<br>表示需要換行,這里用來模擬頁面很長(zhǎng)導(dǎo)致看不見question2。

          可以看到,瀏覽器為列表、鏈接都設(shè)置了默認(rèn)的樣式,鼠標(biāo)移到鏈接上會(huì)變成手型。

          鏈接必須要有一個(gè)href屬性,其值就是目標(biāo)網(wǎng)頁的URL,當(dāng)然可以是本網(wǎng)站內(nèi)部的其他網(wǎng)頁,也可以是外部網(wǎng)站某個(gè)網(wǎng)頁,甚至是本網(wǎng)頁中的其他部分(需要使用元素的id屬性,如例子所示)。

          表單

          表單允許用戶向Web服務(wù)器提交數(shù)據(jù),而不是僅僅用瀏覽器向Web服務(wù)器索要網(wǎng)頁。

          最常用的表單應(yīng)該要數(shù)登錄表單了。用戶通過輸入用戶名和密碼,點(diǎn)擊登錄按鈕向Web服務(wù)器發(fā)起登錄請(qǐng)求。

          表單使用標(biāo)記<form>,在<form>添加供用戶輸入信息的其他內(nèi)容,常用的有文本框、密碼框、單選按鈕、復(fù)選按鈕、下拉列表選擇框以及最后的提交按鈕。我們先簡(jiǎn)單介紹文本框、密碼框以及提交按鈕,其他的以后再介紹。

          先上代碼:

          <!DOCTYPE html>
          <html lang="zh-cmn-hans">
          <head>
          <meta charset="utf-8" />
          <title>這里是網(wǎng)頁的標(biāo)題</title>
          </head>
          <body>
          	<form method="post" action="login-success.html">
          		<label for="user-name">用戶名:</label><input type="text" id="user-name" name="userName" />
          		<label for="password">密碼:</label><input type="password" id="password" name="password" />
          		<input type="submit" value="登錄"/>
          	</form>
          </body>
          </html>
          

          再看看瀏覽器上的呈現(xiàn):

          第一點(diǎn),從呈現(xiàn)上看,用戶名和密碼都是文本框,不過,密碼的文本框會(huì)將輸入信息屏蔽,<input>標(biāo)記使用type屬性來區(qū)分各類輸入方式:text是文本框、password是密碼框、radio是單選按鈕、checkbox是復(fù)選按鈕等。

          其次,我為標(biāo)記指定了id和name兩個(gè)屬性,id屬性用于<label>標(biāo)記for屬性,從而將兩個(gè)元素關(guān)聯(lián)起來,這樣,鼠標(biāo)如果點(diǎn)擊其內(nèi)容,其關(guān)聯(lián)的元素也會(huì)獲得焦點(diǎn)(就是在文本框內(nèi)出現(xiàn)了不斷閃爍的輸入光標(biāo))。

          而name屬性用于標(biāo)識(shí)用戶輸入的該項(xiàng)數(shù)據(jù),這樣Web服務(wù)器才能根據(jù)該名字取出對(duì)應(yīng)的數(shù)據(jù),可以理解為Web服務(wù)器應(yīng)用程序中的變量名,或者參數(shù)名。

          所以,name屬性的值通常遵循后端應(yīng)用程序的開發(fā)規(guī)范,由于我們以后是使用Java Servlet技術(shù)作為后端應(yīng)用的開發(fā)技術(shù)(還有PHP、Python、Go等技術(shù)),所以遵循Java的變量名命名規(guī)范(采用駝峰形式,比如userName)。

          通常,表單中的每一項(xiàng)輸入都會(huì)有一個(gè)關(guān)聯(lián)的<label>元素,用于呈現(xiàn),總不能光出現(xiàn)一個(gè)文本框在那吧,這樣用戶如何知道輸入什么數(shù)據(jù)呢!它有一個(gè)for屬性,用來指定關(guān)聯(lián)元素的id。

          提交按鈕也是使用<input>標(biāo)記,type屬性值是submit,還有一個(gè)value屬性,用來指定按鈕上呈現(xiàn)的文字。

          最后,回過頭來看<form>標(biāo)記,它必須指定一個(gè)action屬性,它的值通常是后端應(yīng)用中處理用戶提交數(shù)據(jù)的一個(gè)程序的URL,比如可以是login.servlet、login.jsp、login.php、login.asp等等,后綴名通常表明了采用的后端應(yīng)用開發(fā)技術(shù)。當(dāng)然,我的例子里直接指定了一個(gè)HTML頁面(login-success.html,你需要?jiǎng)?chuàng)建這么一個(gè)頁面,相信你已經(jīng)知道怎么創(chuàng)建了!),相當(dāng)于不處理用戶提交的數(shù)據(jù),一般不能這么做!

          那么,用戶提交的數(shù)據(jù)是如何提交到Web服務(wù)器的呢?答案當(dāng)然就是HTTP啊,瀏覽器使用HTTP來向Web服務(wù)器請(qǐng)求網(wǎng)頁,再用它來向Web服務(wù)器提交數(shù)據(jù)也就理所當(dāng)然了啊。瀏覽器會(huì)將用戶輸入的信息封裝成HTTP的報(bào)文格式,最后通過網(wǎng)卡發(fā)送出去。

          在這篇文章提到過,HTTP報(bào)文里面含有HTTP方法,常用的有GET、POST等。<form>標(biāo)記的method屬性就是用于指定提交數(shù)據(jù)的HTTP方法。默認(rèn)值是get,但通常使用post,一方面get的語義就是獲取而不是提交。另一方面get會(huì)將表單數(shù)據(jù)作為參數(shù)直接暴露在瀏覽器的地址欄里面。最后get提交的數(shù)據(jù)不能太大。

          我們把上述代碼中的元素的method屬性值修改為get,保存,然后用瀏覽器打開,輸入用戶名和密碼后點(diǎn)擊提交,效果呈現(xiàn)如下:

          可以看到,使用GET方法提交表單數(shù)據(jù)會(huì)在URL上附加上你的數(shù)據(jù),同時(shí)也可以看到<input>標(biāo)記的name屬性值在這所起的作用,就是參數(shù)名的作用。

          總結(jié)

          到此為止,我們就先介紹這么多,我們來總結(jié)一下:

          • 所謂大道至簡(jiǎn),一項(xiàng)技術(shù)的核心思想往往很簡(jiǎn)單,HTML的核心思想就是給信息打標(biāo)記
          • 一個(gè)網(wǎng)頁就是一個(gè)HTML文檔,它就只包含你的信息和標(biāo)記兩種內(nèi)容;
          • HTML負(fù)責(zé)的是數(shù)據(jù)的結(jié)構(gòu)、框架或骨架,就是語義,至于數(shù)據(jù)如何呈現(xiàn),就是樣式(比如呈現(xiàn)在哪個(gè)位置,什么顏色、字體、背景等等)和動(dòng)態(tài)行為是由CSS(層疊樣式表,Cascading Style Sheets)和JavaScript來負(fù)責(zé);
          • HTML、CSS和JavaScript都由瀏覽器來解釋執(zhí)行,所以叫web前端三劍客
          • 既然有web前端三劍客,那就有web后端四劍客(Web服務(wù)器、數(shù)據(jù)庫、緩存、消息隊(duì)列),統(tǒng)稱為web七劍下天山
          • 給你的信息打標(biāo)記時(shí),一定只能考慮語義,尋找最符合語義的標(biāo)記,而不要考慮標(biāo)記的默認(rèn)呈現(xiàn)效果,那只是契約優(yōu)先思想的體現(xiàn);
          • 網(wǎng)頁的語言和字符編碼很重要,字符編碼通常使用utf-8
          • 瀏覽器會(huì)忽略你的信息的格式(縮進(jìn)、換行等),應(yīng)該使用標(biāo)記或CSS來實(shí)現(xiàn)格式;
          • 標(biāo)記有塊級(jí)標(biāo)記和行級(jí)標(biāo)記之分,瀏覽器遇到塊級(jí)標(biāo)記則另起一行展示;
          • 鏈接是網(wǎng)頁的靈魂,使用<a>標(biāo)記創(chuàng)建鏈接,必須指定href屬性
          • 表單用于向Web服務(wù)器提交數(shù)據(jù),使用<form>標(biāo)記創(chuàng)建表單,必須指定action屬性,通常指定method屬性值為post比較安全且傳輸數(shù)據(jù)量較大;
          • 表單中的各項(xiàng)輸入常用<input>標(biāo)記實(shí)現(xiàn),使用type屬性指定各類輸入,如文本框、密碼框、單選、復(fù)選等,通常要為它關(guān)聯(lián)到一個(gè)<label>元素,同時(shí)指定id屬性和name屬性,name屬性的值通常遵從后端技術(shù)的命名規(guī)范。

          習(xí)是一件很痛苦的事情,很多人們總問別人有沒有捷徑,問學(xué)習(xí)路線,好像問完了就學(xué)會(huì)了一樣。其實(shí)我想說是:要是你真的想做一件事,那么就立刻去做好了,因?yàn)闀r(shí)間是不會(huì)等你的,在你猶豫的時(shí)候,時(shí)間早就流走了。所以與其猶豫不決不如理科開始行!

          有的人說學(xué)Java要先學(xué)HTML,那就一起來看HTML是什么吧!

          首先HTML 并不是一種編程語言,而是一種標(biāo)記語超文本標(biāo)記語言,負(fù)責(zé)展示網(wǎng)站的外觀,用來控制各種屬性的展示,要想做JavaWeb開發(fā),HTML是必須學(xué)會(huì)的基礎(chǔ)。

          既然要學(xué)習(xí)開發(fā),那么必須要有工具呀!

          EditPlus 3

          嗯!就先來認(rèn)識(shí)一下HTML的一些標(biāo)簽

          其中的主要的標(biāo)簽如下

          <html>-------------------開始html文檔

          <head>--------------------開始文檔頭部

          <title>---------------------開始文檔標(biāo)題

          This is first page

          </title>---------------------結(jié)束文檔標(biāo)題

          </head>----------------------結(jié)束文檔頭部

          <body>-----------------------開始文檔體

          Hello World.

          </body>------------------------結(jié)束文檔體

          </html>------------------------結(jié)束html文檔

          新建 HTML 頁面就會(huì)出現(xiàn)代碼如下(綠色文字為注釋):

          一個(gè)頁面的整體結(jié)構(gòu)就是:

          所有的內(nèi)容都在<html></html>這兩個(gè)標(biāo)簽內(nèi)部。然后分為 <head> </head>頭部和 <body> </body>身體兩部分。

          文檔的頭部描述了文檔的各種屬性和信息,包括文檔的標(biāo)題、在 Web 中的位置以及和其他文檔的關(guān)系等。

          絕大多數(shù)文檔頭部包含的數(shù)據(jù)都不會(huì)真正作為內(nèi)容顯示給讀者。

          <body>標(biāo)簽包含文檔的所有內(nèi)容

          (比如文本、超鏈接、圖像、表格和列表等等。)

          <title> 定義文檔的標(biāo)題。

          瀏覽器會(huì)以特殊的方式來使用標(biāo)題,并且通常把它放置在瀏覽器窗口的標(biāo)題欄或狀態(tài)欄上。同樣,當(dāng)把文檔加入用戶的鏈接列表或者收藏夾或書簽列表時(shí),標(biāo)題將成為該文檔鏈接的默認(rèn)名稱。

          下面的就算是一個(gè)簡(jiǎn)單的網(wǎng)頁了。

          讓我們保存執(zhí)行一下看看。


          hello world!Java學(xué)習(xí)我來了!

          要: 響應(yīng)式宣言如何解讀,Java中如何進(jìn)行響應(yīng)式編程,Reactor Streams又該如何使用?熱衷于整合框架與開發(fā)工具的阿里云技術(shù)專家杜萬,為大家全面解讀響應(yīng)式編程,分享Spring Webflux的實(shí)踐。

          本篇文章來自于2018年12月22日舉辦的《阿里云棲開發(fā)者沙龍—Java技術(shù)專場(chǎng)》,杜萬專家是該專場(chǎng)第四位演講的嘉賓,本篇文章是根據(jù)杜萬專家在《阿里云棲開發(fā)者沙龍—Java技術(shù)專場(chǎng)》的演講視頻以及PPT整理而成。


          摘要:響應(yīng)式宣言如何解讀,Java中如何進(jìn)行響應(yīng)式編程,Reactor Streams又該如何使用?熱衷于整合框架與開發(fā)工具的阿里云技術(shù)專家杜萬,為大家全面解讀響應(yīng)式編程,分享Spring Webflux的實(shí)踐。從響應(yīng)式理解,到Reactor項(xiàng)目示例,再到Spring Webflux框架解讀,本文帶你進(jìn)入Java響應(yīng)式編程。

          演講嘉賓簡(jiǎn)介:

          杜萬(倚賢),阿里云技術(shù)專家,全棧工程師,從事了12年 Java 語言為主的軟件開發(fā)工作,熱衷于整合框架與開發(fā)工具,Linux擁躉,問題終結(jié)者。合作翻譯《Elixir 程序設(shè)計(jì)》。目前負(fù)責(zé)阿里云函數(shù)計(jì)算的工具鏈開發(fā),正在實(shí)踐 WebFlux 和 Reactor 開發(fā)新的 Web 應(yīng)用。

          本次直播視頻精彩回顧,戳這里!https://yq.aliyun.com/live/721

          PPT下載地址:https://yq.aliyun.com/download/3187

          以下內(nèi)容根據(jù)演講嘉賓視頻分享以及PPT整理而成。

          本文圍繞以下三部分進(jìn)行介紹:

          1.Reactive

          2.Project Reactor

          3.Spring Webflux

          一.Reactive

          1.Reactive Manifesto

          下圖是Reactive Manifesto官方網(wǎng)站上的介紹,這篇文章非常短但也非常精悍,非常值得大家去認(rèn)真閱讀。



          響應(yīng)式宣言是一份構(gòu)建現(xiàn)代云擴(kuò)展架構(gòu)的處方。這個(gè)框架主要使用消息驅(qū)動(dòng)的方法來構(gòu)建系統(tǒng),在形式上可以達(dá)到彈性和韌性,最后可以產(chǎn)生響應(yīng)性的價(jià)值。所謂彈性和韌性,通俗來說就像是橡皮筋,彈性是指橡皮筋可以拉長(zhǎng),而韌性指在拉長(zhǎng)后可以縮回原樣。這里為大家一一解讀其中的關(guān)鍵詞:

          1)響應(yīng)性:快速/一致的響應(yīng)時(shí)間。假設(shè)在有500個(gè)并發(fā)操作時(shí),響應(yīng)時(shí)間為1s,那么并發(fā)操作增長(zhǎng)至5萬時(shí),響應(yīng)時(shí)間也應(yīng)控制在1s左右。快速一致的響應(yīng)時(shí)間才能給予用戶信心,是系統(tǒng)設(shè)計(jì)的追求。

          2)韌性:復(fù)制/遏制/隔絕/委托。當(dāng)某個(gè)模塊出現(xiàn)問題時(shí),需要將這個(gè)問題控制在一定范圍內(nèi),這便需要使用隔絕的技術(shù),避免連鎖性問題的發(fā)生。或是將出現(xiàn)故障部分的任務(wù)委托給其他模塊。韌性主要是系統(tǒng)對(duì)錯(cuò)誤的容忍。

          3)彈性:無競(jìng)爭(zhēng)點(diǎn)或中心瓶頸/分片/擴(kuò)展。如果沒有狀態(tài)的話,就進(jìn)行水平擴(kuò)展,如果存在狀態(tài),就使用分片技術(shù),將數(shù)據(jù)分至不同的機(jī)器上。

          4)消息驅(qū)動(dòng):異步/松耦合/隔絕/地址透明/錯(cuò)誤作為消息/背壓/無阻塞。消息驅(qū)動(dòng)是實(shí)現(xiàn)上述三項(xiàng)的技術(shù)支撐。其中,地址透明有很多方法。例如DNS提供的一串人類能讀懂的地址,而不是IP,這是一種不依賴于實(shí)現(xiàn),而依賴于聲明的設(shè)計(jì)。再例如k8s每個(gè)service后會(huì)有多個(gè)Pod,依賴一個(gè)虛擬的服務(wù)而不是某一個(gè)真實(shí)的實(shí)例,從何實(shí)現(xiàn)調(diào)用1 個(gè)或調(diào)用n個(gè)服務(wù)實(shí)例對(duì)于對(duì)調(diào)用方無感知,這是為分片或擴(kuò)展做了準(zhǔn)備。錯(cuò)誤作為消息,這在Java中是不太常見的,Java中通常將錯(cuò)誤直接作為異常拋出,而在響應(yīng)式中,錯(cuò)誤也是一種消息,和普通消息地位一致,這和JavaScript中的Promise類似。背壓是指當(dāng)上游向下游推送數(shù)據(jù)時(shí),可能下游承受能力不足導(dǎo)致問題,一個(gè)經(jīng)典的比喻是就像用消防水龍頭解渴。因此下游需要向上游聲明每次只能接受大約多少量的數(shù)據(jù),當(dāng)接受完畢再次向上游申請(qǐng)數(shù)據(jù)傳輸。這便轉(zhuǎn)換成是下游向上游申請(qǐng)數(shù)據(jù),而不是上游向下游推送數(shù)據(jù)。無阻塞是通過no-blocking IO提供更高的多線程切換效率。



          2.Reactive Programming

          響應(yīng)式編程是一種聲明式編程范型。下圖中左側(cè)顯示了一個(gè)命令式編程,相信大家都比較熟悉。先聲明兩個(gè)變量,然后進(jìn)行賦值,讓兩個(gè)變量相加,得到相加的結(jié)果。但接著當(dāng)修改了最早聲明的兩個(gè)變量的值后,sum的值不會(huì)因此產(chǎn)生變化。而在Java 9 Flow中,按相同的思路實(shí)現(xiàn)上述處理流程,當(dāng)初始變量的值變化,最后結(jié)果的值也同步發(fā)生變化,這就是響應(yīng)式編程。這相當(dāng)于聲明了一個(gè)公式,輸出值會(huì)隨著輸入值而同步變化。


          響應(yīng)式編程也是一種非阻塞的異步編程。下圖是用reactor.ipc.netty實(shí)現(xiàn)的TCP通信。常見的server中會(huì)用循環(huán)發(fā)數(shù)據(jù)后,在循環(huán)外取出,但在下圖的實(shí)現(xiàn)中沒有,因?yàn)檫@不是使用阻塞模型實(shí)現(xiàn),是基于非阻塞的異步編程實(shí)現(xiàn)。


          響應(yīng)式編程是一種數(shù)據(jù)流編程,關(guān)注于數(shù)據(jù)流而不是控制流。下圖中,首先當(dāng)頁面出現(xiàn)點(diǎn)擊操作時(shí)產(chǎn)生一個(gè)click stream,然后頁面會(huì)將250ms內(nèi)的clickStream緩存,如此實(shí)現(xiàn)了一個(gè)歸組過程。然后再進(jìn)行map操作,得到每個(gè)list的長(zhǎng)度,篩選出長(zhǎng)度大于2的,這便可以得出多次點(diǎn)擊操作的流。這種方法應(yīng)用非常廣泛,例如可以篩選出雙擊操作。由此可見,這種編程方式是一種數(shù)據(jù)流編程,而不是if else的控制流編程。


          之前有提及消息驅(qū)動(dòng),那么消息驅(qū)動(dòng)(Message-driven)和事件驅(qū)動(dòng)(Event-driven)有什么區(qū)別呢。

          1)消息驅(qū)動(dòng)有確定的目標(biāo),一定會(huì)有消息的接受者,而事件驅(qū)動(dòng)是一件事情希望被觀察到,觀察者是誰無關(guān)緊要。消息驅(qū)動(dòng)系統(tǒng)關(guān)注消息的接受者,事件驅(qū)動(dòng)系統(tǒng)關(guān)注事件源。

          2)在一個(gè)使用響應(yīng)式編程實(shí)現(xiàn)的響應(yīng)式系統(tǒng)中,消息擅長(zhǎng)于通訊,事件擅長(zhǎng)于反應(yīng)事實(shí)。

          3.Reactive Streams

          Reactive Streams提供了一套非阻塞背壓的異步流處理標(biāo)準(zhǔn),主要應(yīng)用在JVM、JavaScript和網(wǎng)絡(luò)協(xié)議工作中。通俗來說,它定義了一套響應(yīng)式編程的標(biāo)準(zhǔn)。在Java中,有4個(gè)Reactive Streams API,如下圖所示:


          這個(gè)API中定義了Publisher,即事件的發(fā)生源,它只有一個(gè)subscribe方法。其中的Subscriber就是訂閱消息的對(duì)象。


          作為訂閱者,有四個(gè)方法。onSubscribe會(huì)在每次接收消息時(shí)調(diào)用,得到的數(shù)據(jù)都會(huì)經(jīng)過onNext方法。onError方法會(huì)在出現(xiàn)問題時(shí)調(diào)用,Throwable即是出現(xiàn)的錯(cuò)誤消息。在結(jié)束時(shí)調(diào)用onComplete方法。


          Subscription接口用來描述每個(gè)訂閱的消息。request方法用來向上游索要指定個(gè)數(shù)的消息,cancel方法用于取消上游的數(shù)據(jù)推送,不再接受消息。


          Processor接口繼承了Subscriber和Publisher,它既是消息的發(fā)生者也是消息的訂閱者。這是發(fā)生者和訂閱者間的過渡橋梁,負(fù)責(zé)一些中間轉(zhuǎn)換的處理。

          Reactor Library從開始到現(xiàn)在已經(jīng)歷經(jīng)多代。第0代就是java包Observable 接口,也就是觀察者模式。具體的發(fā)展見下圖:


          第四代雖然仍然是RxJava2,但是相比第三代的RxJava2,其中的小版本有了不一樣的改進(jìn),出現(xiàn)了新特性。

          Reactor Library主要有兩點(diǎn)特性。一是基于回調(diào)(callback-based),在事件源附加回調(diào)函數(shù),并在事件通過數(shù)據(jù)流鏈時(shí)被調(diào)用;二是聲明式編程(Declarative),很多函數(shù)處理業(yè)務(wù)類似,例如map/filter/fold等,這些操作被類庫固化后便可以使用聲明式方法,以在程序中快速便捷使用。在生產(chǎn)者、訂閱者都定義后,聲明式方法便可以用來實(shí)現(xiàn)中間處理者。

          二.Project Reactor

          Project Reactor,實(shí)現(xiàn)了完全非阻塞,并且基于網(wǎng)絡(luò)HTTP/TCP/UDP等的背壓,即數(shù)據(jù)傳輸上游為網(wǎng)絡(luò)層協(xié)議時(shí),通過遠(yuǎn)程調(diào)用也可以實(shí)現(xiàn)背壓。同時(shí),它還實(shí)現(xiàn)了Reactive Streams API和Reactive Extensions,以及支持Java 8 functional API/Completable Future/Stream /Duration等各新特性。下圖所示為Reactor的一個(gè)示例:



          首先定義了一個(gè)words的數(shù)組,然后使用flatMap做映射,再將每個(gè)詞和s做連接,得出的結(jié)果和另一個(gè)等長(zhǎng)的序列進(jìn)行一個(gè)zipWith操作,最后打印結(jié)果。這和Java 8 Stream非常類似,但仍存在一些區(qū)別:

          1)Stream是pull-based,下游從上游拉數(shù)據(jù)的過程,它會(huì)有中間操作例如map和reduce,和終止操作例如collect等,只有在終止操作時(shí)才會(huì)真正的拉取數(shù)據(jù)。Reactive是push-based,可以先將整個(gè)處理數(shù)據(jù)量構(gòu)造完成,然后向其中填充數(shù)據(jù),在出口處可以取出轉(zhuǎn)換結(jié)果。

          2)Stream只能使用一次,因?yàn)樗莗ull-based操作,拉取一次之后源頭不能更改。但Reactive可以使用多次,因?yàn)閜ush-based操作像是一個(gè)數(shù)據(jù)加工廠,只要填充數(shù)據(jù)就可以一直產(chǎn)出。

          3)Stream#parallel()使用fork-join并發(fā),就是將每一個(gè)大任務(wù)一直拆分至指定大小顆粒的小任務(wù),每個(gè)小任務(wù)可以在不同的線程中執(zhí)行,這種多線程模型符合了它的多核特性。Reactive使用Event loop,用一個(gè)單線程不停的做循環(huán),每個(gè)循環(huán)處理有限的數(shù)據(jù)直至處理完成。

          在上例中,大家可以看到很多Reactive的操作符,例如flatMap/concatWith/zipWith等,這樣的操作符有300多個(gè),這可能是學(xué)習(xí)這個(gè)框架最大的壓力。如何理解如此繁多的操作符,可能一個(gè)歸類會(huì)有所幫助:



          1)新序列創(chuàng)建,例如創(chuàng)建數(shù)組類序列等;

          2)現(xiàn)有序列轉(zhuǎn)換,將其轉(zhuǎn)換為新的序列,例如常見的map操作;

          3)從現(xiàn)有的序列取出某些元素;

          4)序列過濾;

          5)序列異常處理。

          6)與時(shí)間相關(guān)的操作,例如某個(gè)序列是由時(shí)間觸發(fā)器定期發(fā)起事件;

          7)序列分割;

          8)序列拉至同步世界,不是所有的框架都支持異步,再需要和同步操作進(jìn)行交互時(shí)就需要這種處理。

          上述300+操作符都有如下所示的彈珠圖(Marble Diagrams),用表意的方式解釋其作用。例如下圖的操作符是指,隨著時(shí)間推移,逐個(gè)產(chǎn)生了6個(gè)元素的序列,黑色豎線表示新元素產(chǎn)生終止。在這個(gè)操作符的作用下,下方只取了前三個(gè)元素,到第四個(gè)元素就不取了。這些彈珠圖大家可以自行了解。



          三.Spring Webflux

          1.Spring Webflux框架

          Spring Boot 2.0相較之前的版本,在基于Spring Framework 5的構(gòu)建添加了新模塊Webflux,將默認(rèn)的web服務(wù)器改為Netty,支持Reactive應(yīng)用,并且Webflux默認(rèn)運(yùn)行在Netty上。而Spring Framework 5也有了一些變化。Java版本最低依賴Java 8,支持Java 9和Java 10,提供許多支持Reactive的基礎(chǔ)設(shè)施,提供面向Netty等運(yùn)行時(shí)環(huán)境的適配器,新增Webflux模塊(集成的是Reactor 3.x)。下圖所示為Webflux的框架:


          左側(cè)是通常使用的框架,通過Servlet API的規(guī)范和Container進(jìn)行交互,上一層是Spring-Webmvc,再上一層則是經(jīng)常使用的一些注解。右側(cè)為對(duì)應(yīng)的Webflux層級(jí),只要是支持NIO的Container,例如Tomcat,Jetty,Netty或Undertow都可以實(shí)現(xiàn)。在協(xié)議層的是HTTP/Reactive Streams。再上一層是Spring-Webflux,為了保持兼容性,它支持這些常用的注解,同時(shí)也有一套新的語法規(guī)則Router Functions。下圖顯示了一個(gè)調(diào)用的實(shí)例:






          在Client端,首先創(chuàng)建一個(gè)WebClient,調(diào)用其get方法,寫入U(xiǎn)RL,接收格式為APPLICATION_STREAM_JSON的數(shù)據(jù),retrieve獲得數(shù)據(jù),取得數(shù)據(jù)后用bodyToFlux將數(shù)據(jù)轉(zhuǎn)換為Car類型的對(duì)象,在doOnNext中打印構(gòu)造好的Car對(duì)象,block方法意思是直到回調(diào)函數(shù)被執(zhí)行才可以結(jié)束。在Server端,在指定的path中進(jìn)行g(shù)et操作,produces和以前不同,這里是application/stream+json,然后返回Flux范型的Car對(duì)象。傳統(tǒng)意義上,如果數(shù)據(jù)中有一萬條數(shù)據(jù),那么便直接返回一萬條數(shù)據(jù),但在這個(gè)示例返回的Flux范型中,是不包含數(shù)據(jù)的,但在數(shù)據(jù)庫也支持Reactive的情況下,request可以一直往下傳遞,響應(yīng)式的批量返回。傳統(tǒng)方式這樣的查詢很有可能是一個(gè)全表遍歷,這會(huì)需要較多資源和時(shí)間,甚至影響其他任務(wù)的執(zhí)行。而響應(yīng)式的方法除了可以避免這種情況,還可以讓用戶在第一時(shí)間看到數(shù)據(jù)而不是等待數(shù)據(jù)采集完畢,這在架構(gòu)體驗(yàn)的完整性上有了很大的提升。application/stream+json也是可以讓前端識(shí)別出,這些數(shù)據(jù)是分批響應(yīng)式傳遞,而不會(huì)等待傳完才顯示。

          現(xiàn)在的Java web應(yīng)用可以使用Servlet棧或Reactive棧。Servlet棧已經(jīng)有很久的使用歷史了,而現(xiàn)在又增加了更有優(yōu)勢(shì)的Reactive棧,大家可以嘗試實(shí)現(xiàn)更好的用戶體驗(yàn)。


          2.Reactive編程模型

          下圖中是Spring實(shí)現(xiàn)的一個(gè)向后兼容模型,可以使用annotation來標(biāo)注Container。這是一個(gè)非常清晰、支持非常細(xì)節(jié)化的模型,也非常利于同事間的交流溝通。


          下圖是一個(gè)Functional編程模型,通過寫函數(shù)的方式構(gòu)造。例如下圖中傳入一個(gè)Request,返回Response,通過函數(shù)的方法重點(diǎn)關(guān)注輸入輸出,不需要區(qū)分狀態(tài)。然后將這些函數(shù)注冊(cè)至Route。這個(gè)模型和Node.js非常接近,也利于使用。




          3.Spring Data框架

          Spring Data框架支持多種數(shù)據(jù)庫,如下圖所示,最常用的是JPA和JDBC。在實(shí)踐中,不同的語言訪問不同的數(shù)據(jù)庫時(shí),訪問接口是不一樣的,這對(duì)編程人員來說是個(gè)很大的工作量。

          Spring Data便是做了另一層抽象,使你無論使用哪種數(shù)據(jù)庫,都可以使用同一個(gè)接口。具體特性這里不做詳談。


          下圖展示了一個(gè)Spring Data的使用示例。只需要寫一個(gè)方法簽名,然后注解為Query,這個(gè)方法不需要實(shí)現(xiàn),因?yàn)榭蚣芎笈_(tái)已經(jīng)采用一些技術(shù),直接根據(jù)findByFirstnameAndLastname就可以查詢到。這種一致的調(diào)用方式無疑提供了巨大的方便。


          現(xiàn)在Reactive對(duì)Spring Data的支持還是不完整的,只支持了MongoDB/Redis/Cassandra和Couchbase,對(duì)JPA/LDAP/Elasticsearch/Neo4j/Solr等還不兼容。但也不是不能使用,例如對(duì)JDBC數(shù)據(jù)庫,將其轉(zhuǎn)為同步即可使用,重點(diǎn)在于findAll和async兩個(gè)函數(shù),這里不再展開詳述,具體代碼如下圖所示:



          Reactive不支持JDBC最根本的原因是,JDBC不是non-blocking設(shè)計(jì)。但是現(xiàn)在JavaOne已經(jīng)在2016年9月宣布了Non-blocking JDBC API的草案,雖然還未得到Java 10的支持,但可見這已經(jīng)成為一種趨勢(shì)。

          四.總結(jié)

          Spring MVC框架是一個(gè)命令式邏輯,方便編寫和調(diào)試。Spring WebFlux也具有眾多優(yōu)勢(shì),但調(diào)試卻不太容易,因?yàn)樗?jīng)常需要切換線程執(zhí)行,出現(xiàn)錯(cuò)誤的棧可能已經(jīng)銷毀。當(dāng)然這也是現(xiàn)今Java的編譯工具對(duì)WebFlux不太友好,相信以后會(huì)改善。下圖中列出了Spring MVC和Spring WebFlux各自的特性及交叉的部分。最后也附上一些參考資料。



          作者:李博bluemind


          主站蜘蛛池模板: 国产天堂在线一区二区三区 | 在线视频一区二区三区三区不卡| 亚洲国产成人久久综合一区77| 无码人妻一区二区三区免费看| 狠狠做深爱婷婷综合一区| 精品国产乱子伦一区二区三区| 伦理一区二区三区| 成人午夜视频精品一区| 精品一区二区三区水蜜桃| 国产剧情一区二区| 波多野结衣电影区一区二区三区 | 精品国产一区二区三区2021| 国产一区二区三区亚洲综合 | 无码毛片一区二区三区视频免费播放 | 中文字幕日韩一区| 精品国产一区二区三区四区 | 国产精品视频一区二区噜噜| 亲子乱AV视频一区二区| 国产成人精品一区二区三区无码 | 亚洲国产精品综合一区在线| 无码成人一区二区| 国产主播福利一区二区| 99精品国产高清一区二区麻豆| 精品国产一区二区三区无码| 精品国产乱码一区二区三区| 日本一区二区三区不卡视频| 亚洲色精品三区二区一区| 久久精品成人一区二区三区| 国产精品一区二区AV麻豆| 秋霞鲁丝片一区二区三区| 亚洲av高清在线观看一区二区| 精品一区二区三区免费观看 | 97久久精品无码一区二区| 国产精品成人免费一区二区| 韩国女主播一区二区| 久久国产精品免费一区二区三区| 久久精品视频一区| 日本免费一区二区在线观看| 国产精品免费视频一区| 不卡一区二区在线| 中文字幕一区日韩精品|