1

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

例如使用:

<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} />

我可以理解为什么这不能按预期工作,因为 EL expr 和标签的解析顺序。因此,我还测试了直接使用 scriptlet 注入

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

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

  • 使用<input而不是<form:input,这意味着我必须完全复制“路径”属性的弹簧代码(不是好主意)
  • 扩展 form:input 标签,将动态属性复制到默认属性中并进行标准标签渲染(不知道是否是一个可行的解决方案,如果 spring 更改其输入标签实现,那么它就无法正常工作了)
  • 枚举我需要的所有属性,这会使标记代码变得庞大且不易维护

我想知道是否有更好的解决方案我还没有想到,或者第二种可能性是否可行。

谢谢

4

1 回答 1

1

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

没有实现允许我根据需要注入属性,所以我改变了方法并尝试生成一个标签,该标签生成一个主体然后对其进行评估。此外,这种方法也不起作用,因为 jsp 和标签是在执行之前编译的,因此无法在标签正文中注入 JSP 代码。

所以我找到了一个目前有效的解决方案,它是这样的:

我创建了自己的输入标签,该标签从 spring 的InputTag.java. 这个标签接受一个叫做dynAttrstype的特殊属性java.util.Map;这些是从我的父标签传递的动态属性。其余有效/接受的标签属性与弹簧输入标签相同。

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

  • 如果属性是类字段,则使用 aPropertyAccessor设置值(例如onClick
  • 如果属性不是类字段(或该字段不可写),那么它将被注入动态属性(例如data-customData

从这里开始,我只需调用 super.writeTagContent() 和瞧,春天为我做了所有的魔法!

使用示例:

<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">
  <input id="model.path" name="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
</div>

所以我可以在运行时在spring的输入标签中动态注入任意数量的动态属性!


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

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

  • 在哈希图中缓存此标记中的所有可访问字段并使用 a 手动更新它们field.setValue(this,dynAttrs.get(attrName))(应该更快,因为它不需要每次调用都检索该字段,但也许是PropertyAccessor一样的?)。

于 2014-06-05T12:48:59.140 回答