2012-10-14

SpringMVC form tag 的 modelAttribute 與 commandName 差異

在使用 spring-form.tld 的 form tag 時發現,有些地方用 commandName(官方文件),有些地方用 modelAttribue,功能好像都是用來指定 formBackingObject 是誰,但為何有兩種用法?

Open Source 的好處,翻 Source Code 去。

先看 spring-webmvc-3.1.2.RELEASE.jar\META-INF\spring-form.tld。

<attribute>
  <description>Name of the model attribute under which the form object is exposed. Defaults to 'command'.</description>
  <name>modelAttribute</name>
  <required>false</required>
  <rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
  <description>Name of the model attribute under which the form object is exposed. Defaults to 'command'.</description>
  <name>commandName</name>
  <required>false</required>
  <rtexprvalue>true</rtexprvalue>
</attribute>
這是唱雙簧嗎?除了名字不一樣,其他都一樣,再看看 org.springframework.web.servlet.tags.form.FormTag.java。
/**
 * Set the name of the form attribute in the model.
 * <p>May be a runtime expression.
 */
public void setModelAttribute(String modelAttribute) {
  this.modelAttribute = modelAttribute;
}

/**
 * Set the name of the form attribute in the model.
 * <p>May be a runtime expression.
 * @see #setModelAttribute
 */
public void setCommandName(String commandName) {
  this.modelAttribute = commandName;
}
賓果,是一樣的東西,用 modelAttribue 就可以了。

再多看一些 source code 確認一下。
public class FormTag extends AbstractHtmlElementTag {

 /** The default HTTP method using which form values are sent to the server: "post" */
 private static final String DEFAULT_METHOD = "post";

 /** The default attribute name: "command" */
 public static final String DEFAULT_COMMAND_NAME = "command";

 /** The name of the '<code>modelAttribute</code>' setting */
 private static final String MODEL_ATTRIBUTE = "modelAttribute";

 /**
  * The name of the {@link javax.servlet.jsp.PageContext} attribute under which the
  * form object name is exposed.
  */
 public static final String MODEL_ATTRIBUTE_VARIABLE_NAME =
   Conventions.getQualifiedAttributeName(AbstractFormTag.class, MODEL_ATTRIBUTE);

 // ...

 private String modelAttribute = DEFAULT_COMMAND_NAME;

 // ...

 /**
  * Writes the opening part of the block '<code>form</code>' tag and exposes
  * the form object name in the {@link javax.servlet.jsp.PageContext}.
  * @param tagWriter the {@link TagWriter} to which the form content is to be written
  * @return {@link javax.servlet.jsp.tagext.Tag#EVAL_BODY_INCLUDE}
  */
 @Override
 protected int writeTagContent(TagWriter tagWriter) throws JspException {
  
   // ...

  // Expose the form object name for nested tags...
  String modelAttribute = resolveModelAttribute();
  this.pageContext.setAttribute(MODEL_ATTRIBUTE_VARIABLE_NAME, modelAttribute, PageContext.REQUEST_SCOPE);
  this.pageContext.setAttribute(COMMAND_NAME_VARIABLE_NAME, modelAttribute, PageContext.REQUEST_SCOPE);

  // ...
 }

 /**
  * Clears the stored {@link TagWriter}.
  */
 @Override
 public void doFinally() {
   
    // ...
   
  this.pageContext.removeAttribute(MODEL_ATTRIBUTE_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
  this.pageContext.removeAttribute(COMMAND_NAME_VARIABLE_NAME, PageContext.REQUEST_SCOPE);
  
  // ...
 }
}
幾乎可以確認是完全一樣的東西。

最後再看看 org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.java。
/**
 * The name of the {@link javax.servlet.jsp.PageContext} attribute under which the
 * command object name is exposed.
 * @deprecated as of Spring 2.5, in favor of {@link FormTag#MODEL_ATTRIBUTE_VARIABLE_NAME}
 */
@Deprecated
public static final String COMMAND_NAME_VARIABLE_NAME =
  Conventions.getQualifiedAttributeName(AbstractFormTag.class, "commandName");
已經 Deprecated 了,證明無誤。
---
---
---

沒有留言:

張貼留言