为什么<h:form>渲染器添加一个隐藏字段,其表单ID为name和value </h:form>

时间:2013-07-09 21:16:08

标签: java forms jsf jsf-2

我正在阅读JSF实现<h:form>渲染。令我惊讶的是,我看到了(在Mojarra,MyFaces + Tomahawk中),他们在encodeBegin()方法上添加了一个隐藏的输入字段。

以下是Mojarra中FormRenderer的示例代码:

@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. 为什么有一个隐藏的输入字段被分配了标识component.getClientId(context),即UIForm组件?隐藏领域的目的是什么?
  2. 在Mojarra,您无法在id上分配自己的<h:form>属性,但可以在MyFaces上进行分配。在每种情况下,JSF如何处理UIForm(例如,当MyFaces明确提供id时)?
  3. Mojarra表单enctype默认为application/x-www-form-urlencoded。它可以支持multipart/form-data还是text/plain
  4. 由于

1 个答案:

答案 0 :(得分: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请求参数时调用{<1}}:

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>上分配自己的ID属性,但您可以在MyFaces上进行分配。在每种情况下,JSF如何处理UIForm(例如,当MyFaces有明确提供的ID时)?

我不确定你在谈论什么。此,

<h:form id="formId">

在Mojarra也适合我。


  

Mojarra form 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,而无需使用第三方API的servlet过滤器。另见其他How to upload files to server using JSP/Servlet?