【问题标题】:injecting dynamic-attributes in a spring tag from a custom tag从自定义标签在弹簧标签中注入动态属性
【发布时间】:2014-07-11 09:56:46
【问题描述】:

我有一个自定义 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 和标签的解析顺序。因此我也测试了直接使用scriptlets注入

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

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

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

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

谢谢

【问题讨论】:

  • 差点忘了,我想到了另一种解决方案:从 scriptlet 输出&lt;form:input,然后再次强制解析标签输出。
  • 我以为我通过使用 jsp:attribute 找到了解决方案,但由于我有许多属性,我必须将它们封装在 foreach 中,因此 jsp:attribute 应用于 c:forEach 元素形式:输入元素! :-( 看起来不存在可行的解决方案。 示例代码:
  • 还在等待这个答案..

标签: spring jakarta-ee spring-mvc tags dynamic-attributes


【解决方案1】:

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

没有允许我根据需要注入属性的实现,因此我改变了方法并尝试生成一个标签,该标签生成一个主体然后对其进行评估。而且这种方法也行不通,因为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">
  <input id="model.path" name="model.path" disabled="disabled" attr1="val1" attr2="val2"/>
</div>

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


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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多