4

<h:form>私はJSF実装のレンダリングを読んでいました。驚いたことに、(Mojarra、MyFaces + Tomahawk では)encodeBegin()メソッドに非表示の入力フィールドが追加されています。

FormRendererMojarraのサンプルコードは次のとおりです。

@Override
public void encodeBegin(FacesContext context, UIComponent component)
      throws IOException {

    rendererParamsNotNull(context, component);

    if (!shouldEncode(component)) {
        return;
    }

    ResponseWriter writer = context.getResponseWriter();
    assert(writer != null);
    String clientId = component.getClientId(context);
    // since method and action are rendered here they are not added
    // to the pass through attributes in Util class.
    writer.write('\n');
    writer.startElement("form", component);
    writer.writeAttribute("id", clientId, "clientId");
    writer.writeAttribute("name", clientId, "name");
    writer.writeAttribute("method", "post", null);
    writer.writeAttribute("action", getActionStr(context), null);
    String styleClass =
          (String) component.getAttributes().get("styleClass");
    if (styleClass != null) {
        writer.writeAttribute("class", styleClass, "styleClass");
    }
    String acceptcharset = (String)
          component.getAttributes().get("acceptcharset");
    if (acceptcharset != null) {
        writer.writeAttribute("accept-charset", acceptcharset,
                              "acceptcharset");
    }

    RenderKitUtils.renderPassThruAttributes(context,
                                            writer,
                                            component,
                                            ATTRIBUTES);
    writer.writeText("\n", component, null);

    // this hidden field will be checked in the decode method to
    // determine if this form has been submitted.         
    writer.startElement("input", component);
    writer.writeAttribute("type", "hidden", "type");
    writer.writeAttribute("name", clientId,
                          "clientId");
    writer.writeAttribute("value", clientId, "value");
    writer.endElement("input");
    writer.write('\n');

    // Write out special hhidden field for partial submits
    String viewId = context.getViewRoot().getViewId();
    String actionURL =
        context.getApplication().getViewHandler().getActionURL(context, viewId);
    ExternalContext externalContext = context.getExternalContext();
    String encodedActionURL = externalContext.encodeActionURL(actionURL);
    String encodedPartialActionURL = externalContext.encodePartialActionURL(actionURL);
    if (encodedPartialActionURL != null) {
        if (!encodedPartialActionURL.equals(encodedActionURL)) {
            writer.startElement("input", component);
            writer.writeAttribute("type", "hidden", "type");
            writer.writeAttribute("name", "javax.faces.encodedURL", null);
            writer.writeAttribute("value", encodedPartialActionURL, "value");
            writer.endElement("input");
            writer.write('\n');
        }
    }

    if (!writeStateAtEnd) {
        context.getApplication().getViewHandler().writeState(context);
        writer.write('\n');
    }
}

私の質問:

  1. id component.getClientId(context)、つまりUIFormコンポーネントが割り当てられる非表示の入力フィールドがあるのはなぜですか? 隠しフィールドの目的は何ですか?
  2. idMojarra では、独自の属性を割り当てるオプションはありませんが、<h:form>MyFaces では可能です。JSF は各ケースでどのように処理UIFormしますか (たとえば、MyFaces が明示的な provided を持っている場合id)?
  3. Mojarra フォームenctypeのデフォルトはapplication/x-www-form-urlencodedです。それはサポートできますmultipart/form-datatext/plain

ありがとう

4

1 に答える 1

8

ID component.getClientId(context) が割り当てられる非表示の入力フィールド、つまり UIForm コンポーネントがあるのはなぜですか? 隠しフィールドの目的は何ですか?

コメントをよく見てください (行番号はMojarra 2.1.19のものです):

153        // this hidden field will be checked in the decode method to
154        // determine if this form has been submitted.         
155        writer.startElement("input", component);
156        writer.writeAttribute("type", "hidden", "type");
157        writer.writeAttribute("name", clientId,
158                              "clientId");
159        writer.writeAttribute("value", clientId, "value");
160        writer.endElement("input");
161        writer.write('\n');

したがって、これはどのフォームが送信されたかを判断するために使用されています。この決定は、FormRenderer#decode()リクエスト値の適用フェーズで JSF が HTTP リクエスト パラメータを決定する必要があるときに呼び出される で行われます。

96         // Was our form the one that was submitted?  If so, we need to set
97         // the indicator accordingly..
98         Map<String, String> requestParameterMap = context.getExternalContext()
99               .getRequestParameterMap();
100        if (requestParameterMap.containsKey(clientId)) {
101            if (logger.isLoggable(Level.FINE)) {
102                logger.log(Level.FINE,
103                           "UIForm with client ID {0}, submitted",
104                           clientId);
105            }
106            ((UIForm) component).setSubmitted(true);
107        } else {
108            ((UIForm) component).setSubmitted(false);
109        }

言い換えれば、それはUIForm#isSubmitted()プロパティの結果を制御します。ページに複数のフォームが含まれる次のユースケースで役立つ場合があります。


Mojarra では、独自の id 属性を割り当てるオプションはありませんが、<h:form>MyFaces では可能です。JSFUIFormはそれぞれの場合 (たとえば、MyFaces が明示的に提供された ID を持っている場合) をどのように扱いますか?

何を言っているのかわからない。これ、

<h:form id="formId">

Mojarra でも問題なく動作します。


Mojarra フォーム enctype は、デフォルトで application/x-www-form-urlencoded に設定されています。multipart/form-data または text/plain をサポートできますか?

これは JSF 仕様に準拠しています。enctypeそして、はい、属性を通常の方法で使用できます。

<h:form enctype="multipart/form-data">

このようなフォームの送信が JSF によって適切に認識されるかどうかは別の話です。JSF 2.2 まで、JSF にはmultipart/form-data. JSF コンポーネント ライブラリは、ファイル アップロード コンポーネントと一緒にサーブレット フィルタを提供することで、これを解決します。通常は、内部で Apache Commons FileUpload を使用します。HttpServletRequest#getPart()JSF 2.2は、サードパーティ API を使用するサーブレット フィルターを必要とせずに、新しい Servlet 3.0 API に直接委譲するだけです。とりわけ、JSP/サーブレットを使用してファイルをサーバーにアップロードする方法を参照してください。

于 2013-07-09T21:29:01.453 に答える