4

我正在阅读 JSF 实现<h:form>渲染。令我惊讶的是,我看到(在 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. 在 Mojarra 中,您无法在 MyFacesid上分配您自己的属性。<h:form>JSF 在每种情况下如何处理UIForm(例如,当 MyFaces 有明确的提供时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 中,您<h:form>无法在 MyFaces 上分配您自己的 id 属性。JSF 在每种情况下如何处理UIForm(例如,当 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 组件库通过提供 servlet 过滤器及其文件上传组件来解决这个问题,通常在后台使用 Apache Commons FileUpload。JSF 2.2 只是直接委托给新的 Servlet 3.0 HttpServletRequest#getPart()API,而不需要使用 3rd 方 API 的 servlet 过滤器。另请参阅如何使用 JSP/Servlet 将文件上传到服务器?

于 2013-07-09T21:29:01.453 回答