JSFチュートリアル(7)-ライフサイクルのRestore View Phase
7411 ワード
JSFマクロのライフサイクルではExecuteとRenderに分けられ、Execute部分では具体的なステップ(前のブログのフローチャートを参照)に分けて6つのステップがあります.後の文章では、筆者がゆっくりとJSFに入ります(JavaEEはコードがどのように実現されるかについては、具体的なコードが異なります).このブログでは、第1段階のRestore View Phaseについて詳しく説明します.
道徳経には「道生一、一生二、二生三、三生万物」とある.いかなる複雑な過程も簡単から始まり、JSFに対しても例外ではなく、JSFが行ったすべての動作は要求によって引き起こされる.通常、この要求のトリガは、ユーザがリンクをクリックしたり、コミットボタンをクリックしたりしたためであり、要求がサーバJSFに到着すると、このステップ(Restore View Phase)が開始される.JSF宣言サイクルに触れたばかりの人は、なぜ最初の段階がRestoreなのか理解できないかもしれません.これは前のJSFに連絡して要求を2種類に分けて話します.JSFにとってリクエストはinitialではなくpostbackなので、1つのリクエストが到着したときにJSFはこのリクエストに対応するviewがデフォルトで格納されているので、すべきことはRestoreというviewです.このviewが保存されていない場合(新しいview)、簡単に直接作成して保存すればいいです.この過程は楽観的なロックに似ていて、すべてが素晴らしいと信じています.素晴らしいことを楽しむ過程で問題に遭遇したとしたら、私たちはそれを解決してから再び美しさに戻ります.
RestoreView Phaseコアexecuteメソッド(jsf-impl-2.1.3,RestoreView Phase.java)
FacesContextには、1つのリクエストを処理するすべての情報が含まれています.すべてのプログラムのコンポーネント、イベントプロセッサ、変換器、検証器はFacesContextのインスタンスに配置されます.したがって、このステップでは、対応するviewが確立され保存されるほか、イベントプロセッサおよび検証期間がviewのコンポーネントに提供され、ユーザーの後続の操作の準備ができます.
JSFではinitialタイプのリクエストがリクエストされた場合(初めて)、JSFは空のviewを作成し、ライフサイクルはRender Responseに直接進み(コード98行から)、このプロセスの中空のviewは表示するページでコンポーネントを参照するtagと一緒に置かれます(実はこの言葉は分かりません!).
リクエストがpostbacks方式のリクエストであれば、対応するこのviewはすでにFacesContextインスタンスにあり、このステップでJSF実装者はクライアントまたはサーバの状態情報に基づいてこのview(コード85行)を復元するが、ここで筆者は公式ドキュメントに答えが見つからず、コード65行はこのViewがnullであるかどうかを判断し、postbackタイプのリクエストであればなぜViewがnullであるのかという問題がある.さらに次のコードで新しいviewを再作成したが,筆者はメソッド名(is 11 CompatEnabled)に基づいて互換性に関係する可能性があると推測した.
Restore Viewフェーズ全体で、コアの目的は異なるリクエストの区別です.initial-->作成+保存;postback-->リカバリ.
道徳経には「道生一、一生二、二生三、三生万物」とある.いかなる複雑な過程も簡単から始まり、JSFに対しても例外ではなく、JSFが行ったすべての動作は要求によって引き起こされる.通常、この要求のトリガは、ユーザがリンクをクリックしたり、コミットボタンをクリックしたりしたためであり、要求がサーバJSFに到着すると、このステップ(Restore View Phase)が開始される.JSF宣言サイクルに触れたばかりの人は、なぜ最初の段階がRestoreなのか理解できないかもしれません.これは前のJSFに連絡して要求を2種類に分けて話します.JSFにとってリクエストはinitialではなくpostbackなので、1つのリクエストが到着したときにJSFはこのリクエストに対応するviewがデフォルトで格納されているので、すべきことはRestoreというviewです.このviewが保存されていない場合(新しいview)、簡単に直接作成して保存すればいいです.この過程は楽観的なロックに似ていて、すべてが素晴らしいと信じています.素晴らしいことを楽しむ過程で問題に遭遇したとしたら、私たちはそれを解決してから再び美しさに戻ります.
RestoreView Phaseコアexecuteメソッド(jsf-impl-2.1.3,RestoreView Phase.java)
public void execute(FacesContext facesContext) throws FacesException {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Entering RestoreViewPhase");
}
if (null == facesContext) {
throw new FacesException(MessageUtils.getExceptionMessageString(
MessageUtils.NULL_CONTEXT_ERROR_MESSAGE_ID));
}
// If an app had explicitely set the tree in the context, use that;
//
UIViewRoot viewRoot = facesContext.getViewRoot();
if (viewRoot != null) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Found a pre created view in FacesContext");
}
facesContext.getViewRoot().setLocale(
facesContext.getExternalContext().getRequestLocale());
// do per-component actions
deliverPostRestoreStateEvent(facesContext);
if (!facesContext.isPostback()) {
facesContext.renderResponse();
}
return;
}
FacesException thrownException = null;
try {
// Reconstitute or create the request tree
Map requestMap = facesContext.getExternalContext().getRequestMap();
String viewId = (String)
requestMap.get("javax.servlet.include.path_info");
if (viewId == null) {
viewId = facesContext.getExternalContext().getRequestPathInfo();
}
// It could be that this request was mapped using
// a prefix mapping in which case there would be no
// path_info. Query the servlet path.
if (viewId == null) {
viewId = (String)
requestMap.get("javax.servlet.include.servlet_path");
}
if (viewId == null) {
viewId = facesContext.getExternalContext().getRequestServletPath();
}
if (viewId == null) {
throw new FacesException(MessageUtils.getExceptionMessageString(
MessageUtils.NULL_REQUEST_VIEW_ERROR_MESSAGE_ID));
}
ViewHandler viewHandler = Util.getViewHandler(facesContext);
boolean isPostBack = (facesContext.isPostback() && !isErrorPage(facesContext));
if (isPostBack) {
facesContext.setProcessingEvents(false);
// try to restore the view
viewRoot = viewHandler.restoreView(facesContext, viewId);
if (viewRoot == null) {
if (is11CompatEnabled(facesContext)) {
// 1.1 -> create a new view and flag that the response should
// be immediately rendered
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Postback: recreating a view for " + viewId);
}
viewRoot = viewHandler.createView(facesContext, viewId);
facesContext.renderResponse();
} else {
Object[] params = {viewId};
throw new ViewExpiredException(
MessageUtils.getExceptionMessageString(
MessageUtils.RESTORE_VIEW_ERROR_MESSAGE_ID,
params),
viewId);
}
}
facesContext.setViewRoot(viewRoot);
facesContext.setProcessingEvents(true);
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Postback: restored view for " + viewId);
}
} else {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("New request: creating a view for " + viewId);
}
String derivedViewId = viewHandler.deriveLogicalViewId(facesContext, viewId);
ViewDeclarationLanguage vdl = viewHandler.getViewDeclarationLanguage(facesContext, derivedViewId);
if (vdl != null) {
// If we have one, get the ViewMetadata...
ViewMetadata metadata = vdl.getViewMetadata(facesContext, viewId);
if (metadata != null) { // perhaps it's not supported
// and use it to create the ViewRoot. This will have, at most
// the UIViewRoot and its metadata facet.
viewRoot = metadata.createMetadataView(facesContext);
// Only skip to render response if there are no view parameters
Collection<UIViewParameter> params =
ViewMetadata.getViewParameters(viewRoot);
if (params.isEmpty()) {
facesContext.renderResponse();
}
}
} else {
facesContext.renderResponse();
}
if (null == viewRoot) {
viewRoot = (Util.getViewHandler(facesContext)).
createView(facesContext, viewId);
}
facesContext.setViewRoot(viewRoot);
assert (null != viewRoot);
}
} catch (FacesException fe) {
thrownException = fe;
} finally {
if (null == thrownException) {
deliverPostRestoreStateEvent(facesContext);
} else {
throw thrownException;
}
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Exiting RestoreViewPhase");
}
}
FacesContextには、1つのリクエストを処理するすべての情報が含まれています.すべてのプログラムのコンポーネント、イベントプロセッサ、変換器、検証器はFacesContextのインスタンスに配置されます.したがって、このステップでは、対応するviewが確立され保存されるほか、イベントプロセッサおよび検証期間がviewのコンポーネントに提供され、ユーザーの後続の操作の準備ができます.
JSFではinitialタイプのリクエストがリクエストされた場合(初めて)、JSFは空のviewを作成し、ライフサイクルはRender Responseに直接進み(コード98行から)、このプロセスの中空のviewは表示するページでコンポーネントを参照するtagと一緒に置かれます(実はこの言葉は分かりません!).
リクエストがpostbacks方式のリクエストであれば、対応するこのviewはすでにFacesContextインスタンスにあり、このステップでJSF実装者はクライアントまたはサーバの状態情報に基づいてこのview(コード85行)を復元するが、ここで筆者は公式ドキュメントに答えが見つからず、コード65行はこのViewがnullであるかどうかを判断し、postbackタイプのリクエストであればなぜViewがnullであるのかという問題がある.さらに次のコードで新しいviewを再作成したが,筆者はメソッド名(is 11 CompatEnabled)に基づいて互換性に関係する可能性があると推測した.
Restore Viewフェーズ全体で、コアの目的は異なるリクエストの区別です.initial-->作成+保存;postback-->リカバリ.