4

Utilityクラスの静的インポートがあります。

<%@ page import="static com.groupgti.webclient.util.MappingUtils.*" %>

このクラスにはいくつかの定数があります。

public static final String HTM = ".htm";

public static final String SECURE_REQUEST_MAPPING = "/secure/";

public static final String CANDIDATE_DETAILS_DATA_FORM_MAPPING = "assessments/candidate-details-data";

SpringMVCフォームがあります。

<form:form cssClass="springForm"
        action="${pageContext.servletContext.contextPath}<%=SECURE_REQUEST_MAPPING + CANDIDATE_DETAILS_DATA_FORM_MAPPING + HTM%>"
        commandName="assessments/candidate-details-request">
</form:form>

なぜ私がこのように使用しているのですか?

<a href="${pageContext.servletContext.contextPath}<%=SECURE_REQUEST_MAPPING + CANDIDATE_DETAILS_DATA_FORM_MAPPING + HTM%>">
   some text
</a>

属性の値はhref正しく生成され、Spring形式actionの属性ではHTMLコードは次のようになります/webclient<%=SECURE_REQUEST_MAPPING + CANDIDATE_DETAILS_DATA_FORM_MAPPING + HTM%>。これらの定数の値は表示されていません。それはなぜですか、それを機能させるにはどうすればよいですか?

4

2 に答える 2

2

職場ではJSPでJavaをインライン化することは許可されていないため、カスタムタグを使用してJSPの静的最終クラスフィールドを「インポート」します。UseConstantsTagこれは、Spring Frameworkのutilsを使用し、一般的なサポートを使用して、放棄されたJakartaの「非標準」カスタムタグライブラリAPIからわずかに変更されています。(現時点では元のコードを見つけることさえできません。ここに元のAPIドキュメントがあります。)

Mapこのタグは基本的に、JSPで簡単に使用できるすべての静的最終フィールドを(リフレクションを介して)公開します。この要点の完全なコードを見てください。本質は次のとおりです。

/**
 * Tag that exposes all of the public constants in a class as a map stored in
 * a scoped attribute. The scope may be specified, but defaults to page scope.
 * <p/>
 * Based on abandoned project taglibs-unstandard, specifically
 * {@code org.apache.taglibs.unstandard.UseConstantsTag}. Uses Spring's TagUtils
 * and ClassUtils instead of utils bundled in taglibs-unstandard, plus it
 * supports generics.
 * 
 * @see http://jakarta.apache.org/taglibs/unstandard
 */
public class UseConstantsTag extends TagSupport {
  private static final long serialVersionUID = 1L;

  /**
   * The fully qualified name of the Java class for which constants are to be
   * exposed.
   */
  private String className;

  /**
   * The scope in which the exposed map will be stored.
   */
  private String scope = TagUtils.SCOPE_PAGE;

  /**
   * The name of the scoped attribute in which the constants will be stored.
   */
  private String var;

  /**
   * Construct an instance of this class.
   */
  public UseConstantsTag() {
  }

  /**
   * Retrieve the name of the class for which constants are to be exposed.
   * 
   * @return The fully qualified class name.
   */
  public String getClassName() {
    return className;
  }

  /**
   * Set the name of the class for which constants are to be exposed.
   * 
   * @param className The fully qualified class name.
   */
  public void setClassName(final String className) {
    this.className = className;
  }

  /**
   * Retrieve the scope in which the exposed map will be stored.
   * 
   * @return The name of the scope.
   */
  public String getScope() {
    return scope;
  }

  /**
   * Set the scope in which the exposed map will be stored.
   * 
   * @param scope The name of the scope.
   */
  public void setScope(final String scope) {
    Assert.notNull(scope, "Scope cannot be null");
    this.scope = scope;
  }

  /**
   * Retrieve the variable name in which the exposed map will be stored.
   * 
   * @return The name of the variable.
   */
  public String getVar() {
    return var;
  }

  /**
   * Set the variable name in which the exposed map will be stored.
   * 
   * @param var The name of the variable.
   */
  public void setVar(final String var) {
    this.var = var;
  }

  /**
   * Expose the constants for a class as a scoped attribute.
   * 
   * @return A constant that identifies what the container should do next.
   * 
   * @throws JspException if a fatal error occurs.
   */
  @Override
  public int doStartTag() throws JspException {
    if (className != null && var != null) {
      Map<String, Object> constants;
      try {
        constants = ClassReflectionUtils.getClassConstants(className);
      } catch (final ClassNotFoundException e) {
        throw new JspTagException("Class not found: " + className, e);
      } catch (final IllegalArgumentException e) {
        throw new JspTagException("Illegal argument: " + className, e);
      } catch (final IllegalAccessException e) {
        throw new JspTagException("Illegal access: " + className, e);
      }
      if (!constants.isEmpty()) {
        pageContext.setAttribute(var, constants, TagUtils.getScope(scope));
      }
    }

    return SKIP_BODY;
  }

  /**
   * Free up any resources being used by this tag handler.
   */
  @Override
  public void release() {
    super.release();
    className = null;
    scope = null;
    var = null;
  }

}

/**
 * Utility class for working with Class instances.
 */
final class ClassReflectionUtils {

  /**
   * Private constructor to prevent instantiation of this class.
   */
  private ClassReflectionUtils() {
  }

  /**
   * Creates and returns a map of the names of public static final constants to
   * their values, for the specified class.
   * 
   * @param className The fully qualified name of the class for which the
   *                  constants should be determined
   * 
   * @return {@code Map<String, Object>} from constant names to values
   * @throws ClassNotFoundException
   * @throws IllegalAccessException
   * @throws IllegalArgumentException
   */
  public static Map<String, Object> getClassConstants(final String className)
      throws ClassNotFoundException, IllegalArgumentException,
      IllegalAccessException {
    final Map<String, Object> constants = new HashMap<String, Object>();
    final Class<?> clazz = ClassUtils.forName(className,
        ClassUtils.getDefaultClassLoader());

    for (final Field field : clazz.getFields()) {
      final int modifiers = field.getModifiers();
      if (Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers)
          && Modifier.isFinal(modifiers)) {
        // null as argument because it's ignored when field is static
        final Object value = field.get(null);
        if (value != null) {
          constants.put(field.getName(), value);
        }
      }
    }
    return constants;
  }

}

タグの定義:

<tag>
    <name>useConstants</name>
    <tag-class>com.github.xaerxess.UseConstantsTag</tag-class>
    <body-content>empty</body-content>

    <display-name>useConstants</display-name>

    <description>
    Exposes all of the public constants in a class as a map stored in
    a scoped attribute. The scope may be specified, but defaults to page
    scope.
     </description>

    <variable>
        <name-from-attribute>var</name-from-attribute>
        <variable-class>java.lang.Object</variable-class>
        <declare>true</declare>
        <scope>AT_BEGIN</scope>
        <description>The name of the attribute into which the map will be stored.</description>
    </variable>

    <attribute>
        <name>var</name>
        <required>yes</required>
        <rtexprvalue>no</rtexprvalue>
        <description>Name of the scoped attribute into which the map will be stored.</description>
    </attribute>

    <attribute>
        <name>className</name>
        <required>yes</required>
        <rtexprvalue>no</rtexprvalue>
        <description>Fully qualified name of the class from which constants will be extracted.</description>
    </attribute>

    <attribute>
        <name>scope</name>
        <required>no</required>
        <rtexprvalue>no</rtexprvalue>
        <description>Scope into which to store the map. Default is page scope.</description>
    </attribute>

    <example>
To expose all of the constants in the Integer class:
<![CDATA[<un:useConstants var="const" className="java.lang.Integer" />]]> 
    </example>
</tag>

次のように使用します。

<custom:useConstants var="MappingUtils" 
    className="com.groupgti.webclient.util.MappingUtils" scope="application" />

その後:

<p>My const: ${MappingUtils.SECURE_REQUEST_MAPPING}</p>
于 2012-09-27T11:39:09.737 に答える
1

<%= ... %>JSPでは、カスタムタグ(など)の属性でスクリプトレット式()を使用できますが<form:form>、属性のコンテンツはこれだけである必要があります。<%= ... %>したがって、カスタムタグの属性で式とEL式またはプレーンテキストを混在させることはできません。

ただし、これらのタグはJSPにとって特別な意味を持たないため、通常のHTMLタグの属性で任意のコンテンツを使用できます。これが、で機能する理由<a>です。

考えられる解決策の1つは、スクリプトレット式の結果をリクエスト属性に入れて、EL式で使用することです。

<c:set var = "url" 
    value = "<%=SECURE_REQUEST_MAPPING + CANDIDATE_DETAILS_DATA_FORM_MAPPING + HTM%>" />
<form:form action="${pageContext.servletContext.contextPath}${url}" ...>
    ...
</form:form>

または、たとえば、:にコンテキストパスを追加するメソッドを定義することにより、ELなしでスクリプトレットを使用することを選択できますMappingUtils

... <%= url(...) %> ...

歴史的な理由から(EL式はスクリプトレットを置き換えるように設計されています)、JSPはELとスクリプトレットを混在させる洗練された方法を提供しないため、この種の問題はかなり予想されます。

于 2012-09-27T11:35:39.997 に答える