jsf登录注册页面
JSF不是我们通常认为的那样。 这也是一个调试起来可能有些棘手的框架,尤其是在初次遇到时。 在这篇文章中,让我们继续探讨为什么会出现这种情况,并提供一些JSF调试技术。 我们将讨论以下主题:
- JSF不是我们经常想到的
- JSF调试的难点
- 如何系统地调试JSF
- JSF的工作原理– JSF生命周期
- 从浏览器调试Ajax请求到服务器再返回
- 调试JSF前端Javascript代码
- 最后的想法–替代方案? (给读者的问题)
JSF不是我们经常想到的
首先,JSF看起来像一个企业Java / XML前端框架,但实际上并不是。 它实际上是一个多语言Java / Java脚本框架,其中客户端Java脚本部分不可忽略,并且理解它也很重要。 它还对直接使用HTML / CSS有很好的支持。
JSF开发人员正在使用ocasion,而他们已经是多种语言的开发人员,其主要语言是Java,但仍需要使用本地语言的Javascript。
JSF调试的难点
在上一篇文章中将JSF与GWT和AngularJS进行比较时,我发现该框架从XML背后的开发人员那里提取HTML和CSS的(最常用的方法)增加了调试的难度,因为它创建了一个额外的层次。间接。
也可以使用直接使用HTML / CSS的更直接的方法,但是似乎企业Java开发人员在大多数情况下倾向于使用XML,因为它是一种更熟悉的技术。 另一个问题是框架/库的客户端Javascript部分没有很好的文档记录,了解发生的事情通常很重要。
系统调试JSF的唯一方法
第一次遇到JSF时,我首先尝试仅从Java,XML和文档中使用它。 虽然我可以那样做一部分工作,但在很多情况下这种方法确实是不够的。
我得出的结论是,为了能够有效地调试JSF应用程序,需要了解以下内容:
- HTML
- CSS
- Java脚本
- HTTP
- Chrome开发工具,Firebug或同等产品
- JSF生命周期
对于大多数使用Java / XML进行工作的开发人员来说,这听起来可能令人惊讶,但是这种以Web为中心的调试JSF的方法是我设法满足许多需要一些重要组件自定义或能够修复某些bug的唯一方法。
让我们首先了解JSF的内部工作原理,以便我们可以对其进行更好的调试。
JSF承担MVC
JSF处理MVC的方式是全部三个组件都位于服务器端:
- 该模型是纯Java对象的树
- 视图是用XML定义的服务器端模板,可读取该模板以构建内存视图定义
- Controller是一个Java Servlet,它接收每个请求并通过一系列步骤处理它们
假定浏览器只是服务器端生成HTML的呈现引擎。 通过提交页面的一部分以进行服务器处理,并请求服务器仅在不离开页面的情况下“重绘”屏幕的一部分,即可实现Ajax。
JSF生命周期
HTTP请求到达后端后,将被JSF Controller捕获,然后将对其进行处理。 该请求经历了称为JSF生命周期的一系列阶段,这对于理解JSF的工作方式至关重要:
JSF生命周期的设计目标
整个生命周期的重点是仅使用浏览器作为渲染平台,在服务器端100%管理MVC。
最初的想法是使呈现平台与服务器端UI组件模型脱钩,从而允许通过交换“呈现响应”阶段来用替代标记语言替换HTML。
这是在2000年代初期,当时HTML很快就可以被基于XML的替代方法取代(但从未出现),然后HTML5出现了。 还有比今天的浏览器更加qwirkier的浏览器,并且跨浏览器的Javascript库的想法尚未普及。
因此,让我们遍历每个阶段,看看如何从浏览器开始进行调试(如果需要)。 让我们以使用Ajax请求的简单示例为基础。
JSF 2 Hello World示例
以下是最小的JSF 2页面,该页面接收来自用户的输入文本,通过Ajax请求将文本发送到后端,并仅刷新输出标签:
<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>
该页面如下所示:
遵循一个Ajax请求–发送至服务器并返回
让我们单击提交以触发Ajax请求,然后使用Chrome开发工具网络标签(右键单击并检查页面上的任何元素)。 这是我们在请求的“表单数据”部分中看到的:
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
该请求说:
输入字段的新值是“ Hello World”,仅将输出字段的新值发送给我,请勿浏览此页面。
让我们看看如何从请求中读取它。 如我们所见,表单的新值被提交到服务器,即“ Hello World”值。 这是几个条目的含义:
-
javax.faces.ViewState
标识从其发出请求的视图。 - 该请求是一个Ajax请求,如标志
javax.faces.partial.ajax
, - 该请求是由
javax.faces.partial.event
定义的单击触发的。
但是那些j_
字符串是什么? 这些是用空格分隔生成HTML元素标识符。 例如,这是我们使用Chrome开发工具查看与j_idt8:input
对应的页面元素的方式:
还有3个额外的表单参数使用这些标识符,这些参数链接到UI组件:
-
javax.faces.source
:发起此请求HTML元素的标识符,在本例中为Submit按钮的ID。 -
javax.faces.execute
:元素的标识符列表,这些元素的值发送到服务器进行处理,在这种情况下为输入文本字段。 -
javax.faces.render
:页面上要“重画”的部分的标识符列表,在这种情况下,仅是输出字段。
但是,当请求到达服务器时会发生什么呢?
JSF生命周期–还原视图阶段
请求到达服务器后,JSF控制器将检查javax.faces.ViewState
并标识它引用的视图。 然后它将构建或还原视图的Java表示,该表示与浏览器端的文档定义在某种程度上相似。
该视图将附加到请求并在整个过程中使用。 通常在应用程序开发期间几乎不需要调试此阶段。
JSF生命周期–应用请求值
然后,JSF控制器将通过请求接收到的新值应用于视图小部件。 该值此时可能无效。 在此阶段,每个JSF组件都会调用其decode
方法。
此方法将从HTTP请求中检索有关小部件的提交值,并将其存储在小部件本身上。
为了调试它,让我们在HtmlInputText
类的decode
方法中放置一个断点,以查看值“ Hello World”:
注意使用我们想要的字段HTML clientId
的条件断点。 这样,即使在带有许多其他相似小部件的大页面中,也可以仅快速调试所需组件的解码。 解码之后的下一个步骤是验证阶段。
JSF生命周期–流程验证
在此阶段,将应用验证,如果发现值有误(例如,日期无效),则请求将绕过“调用应用程序”并直接进入“渲染响应”阶段。
要调试此阶段,可以在processValidators
方法上放置一个类似的断点,或者,如果您碰巧知道哪些是自定义的,可以在验证器中放置一个断点。
JSF生命周期–更新模型
在此阶段,我们知道所有提交的值都是正确的。 JSF现在可以通过将请求中接收到的新值应用于视图模型中的纯Java对象来更新视图模型。
可以通过在有问题的组件的processUpdates
方法中放置一个断点,最终使用类似的条件断点仅在所需的组件上进行破坏,来调试此阶段。
JSF生命周期–调用应用程序
这是最简单的调试阶段。 该应用程序现在具有更新的视图模型,并且可以在其上应用一些逻辑。
这是在XML视图定义中定义的动作侦听器(“动作”属性和侦听器标记)执行的地方。
JSF生命周期–渲染响应
这是我最后调试最多的阶段:为什么未按预期显示该值,等等,都可以在这里找到。 在此阶段,视图和新模型值将从Java对象转换为HTML,CSS和最终的Javascript,并通过电线发送回浏览器。
可以使用相关组件的encodeBegin
, encodeChildren
和encodeEnd
方法中的断点来调试此阶段。
组件将自己渲染或将渲染委托给Renderer
类。
回到浏览器
这是一段漫长的旅程,但我们回到了起点! 这是浏览器收到JSF生成的响应后的样子:
<!--?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部分将要做的是获取部分响应的内容,并逐个更新。
使用更新的ID,客户端JSF回调将搜索具有该ID的组件,将其从文档中删除,然后将其替换为新的更新版本。
在这种情况下,“ Hello World”将显示在“输入”文本字段旁边的标签上!
因此,这就是JSF在后台运行的方式。 但是,如果我们需要调试框架的Javascript部分,该怎么办?
调试JSF Javascript代码
Chrome开发工具可以帮助调试客户端。 例如,假设我们要在触发Ajax请求时暂停客户端。 我们需要转到“源”选项卡,添加XHR(Ajax)断点并触发浏览器操作。 调试器将停止,并且可以检查调用堆栈:
对于诸如Primefaces之类的某些框架,可能会缩小Javascript源(人类不可读),因为它们针对大小进行了优化。
为了解决这个问题,请下载该库的源代码,并以最小的方式构建jar。 通常对此有说明,否则请检查项目poms。 这将在您的Maven资源库中安装一个带有非压缩源的jar进行调试。
UI调试标签:
ui:debug
标记允许使用键盘快捷键查看许多调试信息,有关更多详细信息,请参见 此处。
最后的想法
JSF在企业Java世界中非常流行,并且可以很好地处理许多问题,特别是在UI设计人员考虑使用小部件库的可能性的情况下。
问题在于,通常会有一些功能请求迫使我们深入研究小部件的内部实现以对其进行自定义,这需要HTML,CSS,Javascript和HTTP以及JSF生命周期知识。
杂音是替代品吗?
我们想知道,如果开发人员必须对Web技术有足够的了解,以便能够有效地调试JSF,那么使用这些技术直接构建企业前端(仅是客户端部分)会更简单。
可能会在不久的将来证明Java后端加上仅Javascript前端的多语言方法有效,特别是使用某种客户端MVC框架(例如Angular) 。
这将需要学习更多的Javascript(如果好奇的话,可以看一下Java开发人员的Javascript ),但是无论如何,这对于在JSF中进行自定义小部件开发通常是必需的。
结论和一些疑问(如果有时间的话)
感谢您的阅读,请花一些时间在下面的评论中分享您对这些问题的看法:
- 您是否认为多语种开发(Java / Javascript)通常是可行的选择,尤其是在您的工作场所中?
- 您是否发现基于GWT的框架之一(普通GWT,Vaadin,Errai)或Play框架更易于使用且具有更高的生产率?
jsf登录注册页面