将参数从地图添加到 URL 标记

发布于 2024-07-19 19:54:34 字数 699 浏览 8 评论 0原文

我想向 Struts2 URL 标记添加可变参数列表。 我有会话中对象中的参数(名称值对)的映射。 我正在努力寻找一个好的方法来解决这个问题。 下面是相关的 JSP 代码:

    <s:iterator value="%{#session['com.strutsschool.interceptors.breadcrumbs']}" status="status">
    <s:if test="#status.index > 0">
        &#187;
    </s:if>
    <s:url id="uri" action="%{action}" namespace="%{nameSpace}">
            <s:param name="parameters" value="%{parameters}"/>
    </s:url>
    <nobr><s:a href="%{uri}"><s:property value="displayName"/></s:a></nobr>
</s:iterator>

参数变量是一个包含参数的 Map。 这当然行不通,但我目前看不到解决这个问题的方法。 我目前在想,我可能需要一个自定义的 freemarker 模板。 有人能建议更好的方法吗?

I want to add a variable list of parameters to a Struts2 URL tag. I have a map of the parameters (name value pairs) in an object in the session. I'm struggling to find a good approach to this. Here is the relevant JSP code:

    <s:iterator value="%{#session['com.strutsschool.interceptors.breadcrumbs']}" status="status">
    <s:if test="#status.index > 0">
        »
    </s:if>
    <s:url id="uri" action="%{action}" namespace="%{nameSpace}">
            <s:param name="parameters" value="%{parameters}"/>
    </s:url>
    <nobr><s:a href="%{uri}"><s:property value="displayName"/></s:a></nobr>
</s:iterator>

The parameters variable is a Map that contains the params. This, of course does not work but I cannot see a way to approach this at the moment. I'm thinking at the moment that I might need a custom freemarker template for this. Can anyone suggest a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

江湖彼岸 2024-07-26 19:54:34

也许你可以像这样使用 JSTL 标签,

 <c:url var="uri" value="${namespace}/${action}.action">                
                    <c:forEach items="${parameters}" var="p">
                        <c:param name="${p.key}" value="${p.value}"/>
                    </c:forEach>
</c:url>
<a href="${uri}">Your Link</a>

我知道将 EL 与 OGNL 等混合在一起有些犹豫,但这可行......

Maybe you can use JSTL tags like this

 <c:url var="uri" value="${namespace}/${action}.action">                
                    <c:forEach items="${parameters}" var="p">
                        <c:param name="${p.key}" value="${p.value}"/>
                    </c:forEach>
</c:url>
<a href="${uri}">Your Link</a>

I know there is some hesitation to mix EL with OGNL etc but this works...

平安喜乐 2024-07-26 19:54:34

Parameter 标记仅将参数填充到其直接前代。 将迭代器标签包裹在参数标签周围没有任何效果。 :)
为了解决这个问题,您可以轻松编写一个可以直接使用映射的替代参数标签
该标签可能看起来像这样。

package my.taglibs;

import java.io.Writer;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class ParamTag extends ComponentTagSupport {

    private String map;
    private static final long serialVersionUID = 2522878390854066408L;
    Log log = LogFactory.getLog(ParamTag.class);

    @Override
    public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
        return new Param(stack);
    }

    @Override
    protected void populateParams() {
        super.populateParams();

        Param param = (Param) component;
        param.setMap(map);
    }

    public void setMap(String map) {
        this.map = map;
    }

    public class Param extends Component {

        private String map; 

        public Param(ValueStack stack) {
            super(stack);
        }

        @Override
        public boolean end(Writer writer, String body) {
            Component component = findAncestor(Component.class);
            if (this.map == null) {       
                log.warn("Attribute map is mandatory.");
                return super.end(writer, "");
            }
            Object o = findValue(this.map); //find map in vs
            if(o == null) {
                log.warn("map not found in ValueStack");
                return super.end(writer, "");
            }
            if(!(o instanceof Map)) {
                log.warn("Error in JSP. Attribute map must evaluate to java.util.Map. Found type: " + o.getClass().getName());
                return super.end(writer, "");
            }

            component.addAllParameters((Map) o);
            return super.end(writer, "");
        }

        public void setMap(String map) {
            this.map = map;
        }
    }
}

并且您需要一个相应的顶级域名条目

<tag>
    <description><![CDATA[Parametrize other tags]]></description>
    <name>param</name>
    <tag-class>my.taglibs.ParamTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>map</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <dynamic-attributes>false</dynamic-attributes>
</tag>

The Parameter tag populates parameters only to its direct antecessor. Wrappings an iterator tag around the parameter tag has no effect. :)
To solve this you can easily write an alternative parameter tag wich can use a map direclty
The tag may look like this.

package my.taglibs;

import java.io.Writer;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.components.Component;
import org.apache.struts2.views.jsp.ComponentTagSupport;
import com.opensymphony.xwork2.util.ValueStack;

public class ParamTag extends ComponentTagSupport {

    private String map;
    private static final long serialVersionUID = 2522878390854066408L;
    Log log = LogFactory.getLog(ParamTag.class);

    @Override
    public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
        return new Param(stack);
    }

    @Override
    protected void populateParams() {
        super.populateParams();

        Param param = (Param) component;
        param.setMap(map);
    }

    public void setMap(String map) {
        this.map = map;
    }

    public class Param extends Component {

        private String map; 

        public Param(ValueStack stack) {
            super(stack);
        }

        @Override
        public boolean end(Writer writer, String body) {
            Component component = findAncestor(Component.class);
            if (this.map == null) {       
                log.warn("Attribute map is mandatory.");
                return super.end(writer, "");
            }
            Object o = findValue(this.map); //find map in vs
            if(o == null) {
                log.warn("map not found in ValueStack");
                return super.end(writer, "");
            }
            if(!(o instanceof Map)) {
                log.warn("Error in JSP. Attribute map must evaluate to java.util.Map. Found type: " + o.getClass().getName());
                return super.end(writer, "");
            }

            component.addAllParameters((Map) o);
            return super.end(writer, "");
        }

        public void setMap(String map) {
            this.map = map;
        }
    }
}

And you need a corresponding tld-entry

<tag>
    <description><![CDATA[Parametrize other tags]]></description>
    <name>param</name>
    <tag-class>my.taglibs.ParamTag</tag-class>
    <body-content>JSP</body-content>
    <attribute>
        <name>map</name>
        <required>true</required>
        <rtexprvalue>true</rtexprvalue>
    </attribute>
    <dynamic-attributes>false</dynamic-attributes>
</tag>
丿*梦醉红颜 2024-07-26 19:54:34

您可以使用迭代器来迭代映射

<s:url var="url" action="%{link}" >
  <s:iterator value="parameters.keySet()" var="key">
    <s:param name="%{key}" value="%{parameters.get(#key)}"/>
  </s:iterator>
</s:url>

,但迭代器将消耗参数,因为它是参数的父组件。

查看在 Struts2 中向 URL 添加任意参数了解如何使用导致类似

<s:url var="url" action="%{link}" >
  <s:iterator value="parameters.keySet()" var="key">
    <ob:iterable-param name="%{key}" value="%{parameters.get(#key)}"/>
  </s:iterator>
</s:url>

iterable-param 的自定义标记是一个自定义组件,在父级是迭代器的情况下返回参数的祖父级。

You can iterate over a map using

<s:url var="url" action="%{link}" >
  <s:iterator value="parameters.keySet()" var="key">
    <s:param name="%{key}" value="%{parameters.get(#key)}"/>
  </s:iterator>
</s:url>

but the iterator will consume the parameters as it's the parent component of the param.

Check outAdding arbitrary parameters to a URL in Struts2 for how to do this with a custom tag which results in the similar

<s:url var="url" action="%{link}" >
  <s:iterator value="parameters.keySet()" var="key">
    <ob:iterable-param name="%{key}" value="%{parameters.get(#key)}"/>
  </s:iterator>
</s:url>

iterable-param is a custom component that returns the grandparent of the param in the case where the parent is an iterator.

金橙橙 2024-07-26 19:54:34

参考评论 3,请说明您将如何在 jsp 中使用此自定义标记来实现所需的行为。

另外,要使用评论 1 中提到的解决方案,我们需要在 tld 文件中添加什么条目?

请让我知道这一点。

With reference to comment 3, please show how would you use this customized tag in your jsp to achive the required behaviour.

Also, to use the solution mentioned in comment 1, what is the entry that we need to do in a tld file?

Please let me know this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文