从自定义标记在spring标记中注入动态属性

从自定义标记在spring标记中注入动态属性,spring,jakarta-ee,spring-mvc,tags,dynamic-attributes,Spring,Jakarta Ee,Spring Mvc,Tags,Dynamic Attributes,我有一个自定义jsp标记,它输出一个spring表单输入字段(加上其他布局元素)。我需要做的是能够接受动态属性并按原样在输入字段中使用它们 使用方法: <mytag:myinputtag arbitraryAttribute="value"/> 应该输出 <input:form arbitraryAttribute="value" /> 不幸的是,它没有按预期工作,因为它抛出了一个未终止的表单:输入标记异常。 以下是我使用的代码: <%@ tag dyn

我有一个自定义jsp标记,它输出一个spring表单输入字段(加上其他布局元素)。我需要做的是能够接受动态属性并按原样在输入字段中使用它们

使用方法:

<mytag:myinputtag arbitraryAttribute="value"/>

应该输出

<input:form arbitraryAttribute="value" />

不幸的是,它没有按预期工作,因为它抛出了一个未终止的表单:输入标记异常。 以下是我使用的代码:

<%@ tag dynamic-attributes="attributes" %>
<c:set var="expandedAttributes">
  <c:forEach var="a" items="${ attributes }">
    ${a.key}="${a.value}"<%= " " %>
  </c:forEach> 
</c:set>

<form:input (...) ${expandedAttributes} />

${a.key}=“${a.value}”
我能理解为什么这不能像预期的那样工作,因为EL-expr和标签的分辨率顺序。因此,我还测试了使用scriptlet直接注入

<form:input (...) <%= (String)jspContext.getAttribute("expandedAttributes")%>  --%>

因此,我需要解决这个问题,因为我无法预览可以添加到输入中的所有属性。因此,我想到了以下可能性:


  • 使用
    在这个问题上工作了一个月之后,我考虑了放弃并删除标记文件AllToghter

    没有一个实现允许我按照自己的意愿注入属性,所以我改变了方法,尝试生成一个生成主体的标记,然后对其进行求值。此外,这种方法不起作用,因为jsp和标记是在执行之前编译的,因此不可能在标记体中插入jsp代码

    因此,我找到了一个目前有效的解决方案,如下所示:

    我已经创建了我自己的输入标记,它扩展自spring的
    InputTag.java
    。 此标记接受一个名为
    dynAttrs
    的特殊属性,其类型为
    java.util.Map
    ;这些是从父标记传递的动态属性。其余有效/可接受的标记属性与spring输入标记相同

    然后在
    writeTagContent
    方法中,我检查
    dynAttrs
    是否可用,并且对于每个属性,我检查:

    • 如果属性是类字段,请使用
      PropertyAccessor
      设置值(例如
      onClick
    • 如果属性不是类字段(或字段不可写),则将其注入动态属性中(例如,
      data customData
    从现在起,我只需调用super.writeTagContent(),瞧,spring为我带来了所有的魔力

    用法示例:

    <my:customTextField path="model.path" attr1="val1" attr2="val2" disabled="true"/>
    
    
    
    它将在未来发生变化

    <div class="bla bla bla">
      <my:input path="model.path" disabled="true" dynAttrs="[{attr1,val1},{attr2,val2}]"/>
    </div>
    
    <div class="bla bla bla">
      <form:input path="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
    </div>
    
    
    
    顺流而下变成了

    <div class="bla bla bla">
      <my:input path="model.path" disabled="true" dynAttrs="[{attr1,val1},{attr2,val2}]"/>
    </div>
    
    <div class="bla bla bla">
      <form:input path="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
    </div>
    
    
    
    然后将被渲染为

    <div class="bla bla bla">
      <input id="model.path" name="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
    </div>
    
    
    
    因此,我可以在运行时在spring的输入标记中动态注入任意数量的动态属性


    注意:由于我不喜欢这种方法,因此我准备了此解决方案的另外两种实现:

    • 使用apache common的BeanUtils.populate直接使用dynAttrs填充标记,但在这种情况下,错误管理可能非常关键

    • 将此标记中的所有可访问字段缓存在hashmap中,并使用
      field.setValue(这个,dynAttrs.get(attrName))
      手动更新它们(应该更快,因为它不需要每次调用都检索字段,但可能
      PropertyAccessor
      也会这样做?)


    差点忘了,我想到了另一个解决方案:输出
    ,我以为我是通过使用jsp:attribute找到解决方案的,但是由于我有许多属性,我必须将它们封装在foreach中,因此jsp:attribute应用于c:foreach元素而不是form:input元素!:-(看起来不存在可行的解决方案。示例代码:${attr.value}仍在等待此问题的答案。)。。