javascript
JSF的工作方式和调试方式–可以使用polyglot吗?
JSF不是我們通常認(rèn)為的那樣。 這也是一個(gè)調(diào)試起來可能有些棘手的框架,尤其是在初次遇到時(shí)。 在這篇文章中,讓我們繼續(xù)探討為什么會(huì)出現(xiàn)這種情況,并提供一些JSF調(diào)試技術(shù)。 我們將討論以下主題:
- JSF不是我們經(jīng)常想到的
- JSF調(diào)試的難點(diǎn)
- 如何系統(tǒng)地調(diào)試JSF
- JSF的工作原理– JSF生命周期
- 從瀏覽器調(diào)試Ajax請(qǐng)求到服務(wù)器再返回
- 調(diào)試JSF前端Javascript代碼
- 最后的想法–替代方案? (給讀者的問題)
JSF不是我們經(jīng)常想到的
首先,JSF看起來像一個(gè)企業(yè)Java / XML前端框架,但實(shí)際上并不是 。 它實(shí)際上是一個(gè)多語言Java / Java腳本框架,其中客戶端Java腳本部分不可忽視,并且理解它也很重要。 它還對(duì)直接使用HTML / CSS有很好的支持。
JSF開發(fā)人員正在使用ocasion,而他們已經(jīng)是多種語言的開發(fā)人員,其主要語言是Java,但仍需要使用本地語言的Javascript。
JSF調(diào)試的難點(diǎn)
在上一篇文章中將JSF與GWT和AngularJS進(jìn)行比較時(shí) ,我發(fā)現(xiàn)該框架從XML背后的開發(fā)人員那里提取HTML和CSS的(最常用的)方法增加了調(diào)試的難度,因?yàn)樗鼊?chuàng)建了一個(gè)額外的層次。間接。
也可以使用直接使用HTML / CSS的更直接的方法 ,但是似乎企業(yè)Java開發(fā)人員在大多數(shù)情況下傾向于使用XML,因?yàn)樗且环N更熟悉的技術(shù)。 另一個(gè)問題是框架/庫(kù)的客戶端Javascript部分沒有很好的文檔記錄,了解發(fā)生的事情通常很重要。
系統(tǒng)調(diào)試JSF的唯一方法
第一次遇到JSF時(shí),我首先嘗試僅從Java,XML和文檔中使用它。 雖然我可以那樣做一部分工作,但在很多情況下這種方法確實(shí)是不夠的。
我得出的結(jié)論是,為了能夠有效地調(diào)試JSF應(yīng)用程序,需要了解以下內(nèi)容:
- HTML
- CSS
- Java腳本
- HTTP
- Chrome開發(fā)工具,Firebug或同等功能
- JSF生命周期
對(duì)于大多數(shù)使用Java / XML進(jìn)行工作的開發(fā)人員來說,這聽起來可能令人驚訝,但是這種以Web為中心的調(diào)試JSF的方法是我設(shè)法滿足許多需要一些重要組件自定義或能夠修復(fù)某些bug的唯一方法。
讓我們首先了解JSF的內(nèi)部工作原理,以便我們可以對(duì)其進(jìn)行更好的調(diào)試。
JSF接受MVC
JSF處理MVC的方式是全部三個(gè)組件都位于服務(wù)器端:
- 該模型是純Java對(duì)象的樹
- 視圖是用XML定義的服務(wù)器端模板,可以讀取它以構(gòu)建內(nèi)存視圖定義
- Controller是一個(gè)Java Servlet,它接收每個(gè)請(qǐng)求并通過一系列步驟處理它們
假定瀏覽器只是服務(wù)器端生成HTML的呈現(xiàn)引擎。 通過提交頁面的一部分以進(jìn)行服務(wù)器處理,并請(qǐng)求服務(wù)器僅在不離開頁面的情況下“重繪”屏幕的某些部分,即可實(shí)現(xiàn)Ajax。
JSF生命周期
HTTP請(qǐng)求到達(dá)后端后,將被JSF Controller捕獲,然后將對(duì)其進(jìn)行處理。 該請(qǐng)求經(jīng)歷了稱為JSF生命周期的一系列階段,這對(duì)于理解JSF的工作方式至關(guān)重要:
JSF生命周期的設(shè)計(jì)目標(biāo)
整個(gè)生命周期的重點(diǎn)是僅使用瀏覽器作為呈現(xiàn)平臺(tái),在服務(wù)器端100%管理MVC。
最初的想法是使呈現(xiàn)平臺(tái)與服務(wù)器端UI組件模型脫鉤,以便通過交換“呈現(xiàn)響應(yīng)”階段來用替代標(biāo)記語言替換HTML。
這是在2000年代初期,當(dāng)時(shí)HTML很快就可以被基于XML的替代方法取代(但從未出現(xiàn)),然后HTML5出現(xiàn)了。 瀏覽器的功能要比當(dāng)今更加強(qiáng)大,并且跨瀏覽器的Javascript庫(kù)的想法尚未普及。
因此,讓我們遍歷每個(gè)階段,看看如何從瀏覽器開始進(jìn)行調(diào)試(如果需要)。 讓我們以使用Ajax請(qǐng)求的簡(jiǎn)單示例為基礎(chǔ)。
JSF 2 Hello World示例
以下是最小的JSF 2頁面,該頁面接收來自用戶的輸入文本,通過Ajax請(qǐng)求將文本發(fā)送到后端,并僅刷新輸出標(biāo)簽:
<h:body> <h3>JSF 2.2 Hello World Example</h3><h:form><h:outputtext id="output" value="#{simpleFormBean.inputText}"></h:outputtext> <h:inputtext id="input" value="#{simpleFormBean.inputText}"></h:inputtext><h:commandbutton value="Submit" action="index"><f:ajax execute="input" render="output"></f:ajax></h:commandbutton></h:form> </h:body>該頁面如下所示:
遵循一個(gè)Ajax請(qǐng)求–發(fā)送至服務(wù)器并返回
讓我們單擊提交以觸發(fā)Ajax請(qǐng)求,然后使用Chrome開發(fā)工具網(wǎng)絡(luò)標(biāo)簽(右鍵單擊并檢查頁面上的任何元素)。 這是我們?cè)谡?qǐng)求的“表單數(shù)據(jù)”部分中看到的:
j_idt8:input: Hello World javax.faces.ViewState: -2798727343674530263:954565149304692491 javax.faces.source: j_idt8:j_idt9 javax.faces.partial.event: click javax.faces.partial.execute: j_idt8:j_idt9 j_idt8:input javax.faces.partial.render: j_idt8:output javax.faces.behavior.event: action javax.faces.partial.ajax:true該請(qǐng)求說:
輸入字段的新值是“ Hello World”,僅將輸出字段的新值發(fā)送給我,請(qǐng)勿瀏覽此頁面。
讓我們看看如何從請(qǐng)求中讀取它。 如我們所見,表單的新值被提交到服務(wù)器,即“ Hello World”值。 這是幾個(gè)條目的含義:
- javax.faces.ViewState標(biāo)識(shí)從其發(fā)出請(qǐng)求的視圖。
- 該請(qǐng)求是一個(gè)Ajax請(qǐng)求,如標(biāo)志javax.faces.partial.ajax ,
- 該請(qǐng)求是由javax.faces.partial.event定義的單擊觸發(fā)的。
但是,這些j_字符串是什么? 這些是用空格分隔生成HTML元素標(biāo)識(shí)符。 例如,這是我們使用Chrome開發(fā)工具查看與j_idt8:input對(duì)應(yīng)的頁面元素的方式:
還有3個(gè)額外的表單參數(shù)使用這些標(biāo)識(shí)符,這些參數(shù)鏈接到UI組件:
- javax.faces.source :發(fā)起此請(qǐng)求HTML元素的標(biāo)識(shí)符,在本例中為Submit按鈕的ID。
- javax.faces.execute :元素的標(biāo)識(shí)符列表,這些元素的值發(fā)送到服務(wù)器進(jìn)行處理,在這種情況下為輸入文本字段。
- javax.faces.render :頁面上要“重畫”的部分的標(biāo)識(shí)符列表,在這種情況下,僅是輸出字段。
但是,當(dāng)請(qǐng)求到達(dá)服務(wù)器時(shí)會(huì)發(fā)生什么呢?
JSF生命周期–還原視圖階段
請(qǐng)求到達(dá)服務(wù)器后,JSF控制器將檢查
javax.faces.ViewState并標(biāo)識(shí)它引用的視圖。 然后它將構(gòu)建或還原視圖的Java表示,該表示與瀏覽器端的文檔定義在某種程度上相似。
該視圖將附加到請(qǐng)求并在整個(gè)過程中使用。 通常在應(yīng)用程序開發(fā)期間幾乎不需要調(diào)試此階段。
JSF生命周期–應(yīng)用請(qǐng)求值
然后,JSF控制器將通過請(qǐng)求接收到的新值應(yīng)用于視圖小部件。 該值此時(shí)可能無效。 在此階段,每個(gè)JSF組件都會(huì)調(diào)用其decode方法。
此方法將從HTTP請(qǐng)求中檢索相關(guān)小部件的提交值,并將其存儲(chǔ)在小部件本身上。
為了調(diào)試它,讓我們?cè)贖tmlInputText類的decode方法中放置一個(gè)斷點(diǎn),以查看值“ Hello World”:
注意使用所需字段HTML clientId的條件斷點(diǎn)。 這樣,即使在帶有許多其他相似小部件的大頁面中,也可以僅快速調(diào)試所需組件的解碼。 解碼之后的下一個(gè)步驟是驗(yàn)證階段。
JSF生命周期–流程驗(yàn)證
在此階段,將應(yīng)用驗(yàn)證,如果發(fā)現(xiàn)值有誤(例如,日期無效),則請(qǐng)求將繞過“調(diào)用應(yīng)用程序”并直接進(jìn)入“渲染響應(yīng)”階段。
要調(diào)試此階段,可以在processValidators方法上放置一個(gè)類似的斷點(diǎn),或者,如果您碰巧知道哪些是自定義的,則可以在驗(yàn)證器本身上放置。
JSF生命周期–更新模型
在此階段,我們知道所有提交的值都是正確的。 JSF現(xiàn)在可以通過將請(qǐng)求中接收到的新值應(yīng)用于視圖模型中的純Java對(duì)象來更新視圖模型。
通過在相關(guān)組件的processUpdates方法中放置一個(gè)斷點(diǎn),最終使用類似的條件斷點(diǎn)僅在所需的組件上進(jìn)行中斷,可以調(diào)試此階段。
JSF生命周期–調(diào)用應(yīng)用程序
這是最簡(jiǎn)單的調(diào)試階段。 該應(yīng)用程序現(xiàn)在具有更新的視圖模型,并且可以在其上應(yīng)用一些邏輯。
這是在XML視圖定義中定義的動(dòng)作偵聽器(“動(dòng)作”屬性和偵聽器標(biāo)記)執(zhí)行的地方。
JSF生命周期–渲染響應(yīng)
這是我最后調(diào)試最多的階段:為什么未按預(yù)期顯示該值,等等,都可以在這里找到。 在此階段,視圖和新模型值將從Java對(duì)象轉(zhuǎn)換為HTML,CSS和最終的Javascript,并通過電線發(fā)送回瀏覽器。
可以使用相關(guān)組件的encodeBegin , encodeChildren和encodeEnd方法中的斷點(diǎn)來調(diào)試此階段。
組件將自己渲染或?qū)秩疚薪oRenderer類。
回到瀏覽器
這是一段漫長(zhǎng)的旅程,但我們回到了起點(diǎn)! 這是瀏覽器收到JSF生成的響應(yīng)后的樣子:
<!--?xml version='1.0' encoding='UTF-8'?--> <partial-response> <changes><update id="j_idt8:output"><span id="j_idt8:output"></span></update><update id="javax.faces.ViewState">-8188482707773604502:6956126859616189525></update></changes> </partial-response>框架的Javascript部分將要做的是獲取部分響應(yīng)的內(nèi)容,并逐個(gè)更新。
使用更新的ID,客戶端JSF回調(diào)將搜索具有該ID的組件,將其從文檔中刪除,然后將其替換為新的更新版本。
在這種情況下,“ Hello World”將顯示在“輸入”文本字段旁邊的標(biāo)簽上!
因此,這就是JSF在后臺(tái)運(yùn)行的方式。 但是,如果我們需要調(diào)試框架的Javascript部分,該怎么辦?
調(diào)試JSF Javascript代碼
Chrome開發(fā)工具可以幫助調(diào)試客戶端。 例如,假設(shè)我們要在觸發(fā)Ajax請(qǐng)求時(shí)暫停客戶端。 我們需要轉(zhuǎn)到“源”選項(xiàng)卡,添加XHR(Ajax)斷點(diǎn)并觸發(fā)瀏覽器操作。 調(diào)試器將停止,并且可以檢查調(diào)用堆棧:
對(duì)于諸如Primefaces之類的某些框架,可能會(huì)縮小Javascript源(人類不可讀),因?yàn)樗鼈冡槍?duì)大??小進(jìn)行了優(yōu)化。
要解決此問題,請(qǐng)下載該庫(kù)的源代碼,并以最小的方式構(gòu)建jar。 通常對(duì)此有說明,否則請(qǐng)檢查項(xiàng)目poms。 這將在您的Maven資源庫(kù)中安裝一個(gè)具有非最小化源的jar進(jìn)行調(diào)試。
UI調(diào)試標(biāo)簽:
ui:debug標(biāo)記允許使用鍵盤快捷鍵查看許多調(diào)試信息,有關(guān)更多詳細(xì)信息,請(qǐng)參見此處 。
最后的想法
JSF在企業(yè)Java世界中非常流行,并且可以很好地處理許多問題,特別是在UI設(shè)計(jì)人員考慮使用小部件庫(kù)的可能性的情況下。
問題在于,通常會(huì)有一些功能請(qǐng)求迫使我們深入研究小部件的內(nèi)部實(shí)現(xiàn)以對(duì)其進(jìn)行自定義,這需要HTML,CSS,Javascript和HTTP以及JSF生命周期知識(shí)。
雜音是替代品嗎?
我們想知道,如果開發(fā)人員必須對(duì)Web技術(shù)有足夠的了解,以便能夠有效地調(diào)試JSF,那么使用這些技術(shù)直接構(gòu)建企業(yè)前端(僅是客戶端部分)會(huì)更簡(jiǎn)單。
可能會(huì)在不久的將來證明Java后端加上僅Javascript前端的多語言方法有效,特別是使用某種客戶端MVC框架(例如Angular) 。
這將需要學(xué)習(xí)更多的Javascript(如果好奇的話,可以看一下Java開發(fā)人員的Javascript ),但是無論如何,這對(duì)于在JSF中進(jìn)行自定義小部件開發(fā)通常是必需的。
結(jié)論和一些疑問(如果有時(shí)間的話)
感謝您的閱讀,請(qǐng)花點(diǎn)時(shí)間在下面的評(píng)論中分享您對(duì)這些問題的看法:
- 您是否認(rèn)為多語種開發(fā)(Java / Javascript)通常是可行的選擇,尤其是在您的工作場(chǎng)所中?
- 您是否發(fā)現(xiàn)基于GWT的框架之一(普通GWT,Vaadin,Errai)或Play框架更易于使用且具有更高的生產(chǎn)率?
翻譯自: https://www.javacodegeeks.com/2014/09/how-jsf-works-and-how-to-debug-it-is-polyglot-an-alternative.html
總結(jié)
以上是生活随笔為你收集整理的JSF的工作方式和调试方式–可以使用polyglot吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaOne 2014:会议与合同利益
- 下一篇: 无状态Spring安全性第1部分:无状态