Pregunta

Quiero añadir una lista variable de parámetros a una etiqueta URL Struts2. Tengo un mapa de los parámetros (pares de nombre y valor) en un objeto en la sesión. Estoy luchando para encontrar una buena aproximación a este. Aquí está el código correspondiente 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>

La variable de parámetros es un mapa que contiene los parametros. Esto, por supuesto no funciona, pero no puedo ver una manera de abordar esto en el momento. Estoy pensando en el momento en que puede ser que necesite una plantilla personalizada para este FreeMarker. ¿Puede alguien sugerir una mejor manera?

¿Fue útil?

Solución

La etiqueta de parámetro rellena parámetros sólo a su antecesor directo. Envolturas de una etiqueta de iterador alrededor de la etiqueta parámetro no tiene efecto. :) Para solucionar esto se puede escribir fácilmente un wich etiqueta de parámetro alternativa puede utilizar un mapa direclty de La etiqueta puede tener este aspecto.

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

Y se necesita un TLD-entrada correspondiente

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

Otros consejos

Tal vez se puede utilizar etiquetas JSTL como este

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

Sé que hay algunas dudas para mezclar con EL OGNL, etc, pero esto funciona ...

Puede repetir un mapa utilizando

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

pero el iterador consumirá los parámetros ya que es el componente principal del parámetro.

Adición de parámetros arbitrarios a una URL en Struts2 para saber cómo hacerlo esto con una costumbre de etiquetas que se traduce en el similares

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

iterables-param es un componente personalizado que devuelve el abuelo del parámetro en el caso de que el padre es un iterador.

Con referencia a comentar 3, por favor mostrar cómo usarías esta etiqueta personalizada en su JSP a achive el comportamiento requerido.

Además, al utilizar la solución indicada en el comentario 1, ¿cuál es la entrada que tenemos que hacer en un archivo TLD?

Por favor, hágamelo saber esto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top