2011-07-20 8 views
7

tengo un JSP que necesita para imprimir algún texto que se produce tomando iterador bucle y dársela a otro objeto (frijol de primavera), algo así como:Llamar a un método con el parámetro de rizo interior JSTL

<c:forEach var="myVar" items="${myVars}"> 
    <c:out value="anotherObject.getFoo(myVar)"/> 
</c:forEach> 

Obviamente el código anterior no es válido ya que el operador JSTL . solo permite invocaciones sin parámetros. Veo siguientes soluciones al problema:

1) Scriptlets

<c:forEach var="myVar" items="${myVars}"> 
    <% 
    SomeType myVar = (SomeType) pageContext.getAttribute("myVar"); 
    SomeOtherType anotherObject = (SomeOtherType) pageContext.getAttribute("anotherObject"); 
    YetAnotherType result = anotherObject.getFoo(myVar); 
    pageContext.setAttribute("result", result); 
    %> 
    <c:out value="${result}"/> 
</c:forEach> 

El aire aquí es obvia JSP código de la contaminación y la fealdad general.

2) Escribiendo una etiqueta que hace lo que sea que se haga dentro de scriptlets. Ejemplo típico de sobre-ingeniería, ¡puaj!

3) descomponer una colección de myVars y reemplazar cada myVar con un dynamic proxy, InvocationHandler de lo que añadiría método sin parámetros extra para hacer que todas las llamadas a través getFoo()anotherObject. Todo eso se haría en el controlador para que JSP permanezca limpio y myVar se mantenga igual. ¿Pero a qué precio?

No puedo agregar .getFoo() método al myVar porque no encaja allí y rompería la separación de las preocupaciones.

Parece que los parámetros de aprobación serán posibles en JSP/EL 2.2, pero estoy usando Tomcat 6.0.29, que solo incluye el EL 2.1 API.

Pregunta: ¿Alguien puede sugerir el enfoque más limpio para esta situación?

Respuesta

2

Así es como lo he hecho al final.

En lugar de pasar una colección de instancias SomeType, estoy pasando un mapa. Las claves del mapa son las mismas SomeType sy los valores son instancias de la clase interna específica del controlador, llamémoslo SomeTypeSupplement.

SomeTypeSupplement agrega los captadores necesarios sin arg y conecta todo junto. JSP ahora itera sobre las entradas del mapa y puede recuperar los datos a través de JSTL.

De esta manera evito Proxy TLDs mágicos e innecesarios, mantengo las JSP ordenadas y razonablemente seguras.

1

Si no puede cumplir con scriptlets (su alternativa 1), crearía una etiqueta personalizada para ella (su alternativa 2) o una función EL personalizada. No estoy de acuerdo en que sea una "sobre-ingeniería", es usar las herramientas disponibles para su propósito previsto.

Su alternativa 3, sin embargo, no me gusta. En todo caso, ESO está sobre-ingeniería y hará que su sistema sea innecesariamente complejo y más difícil de seguir para otras personas. Cumpla con las intenciones de las especificaciones y estándares en los que está trabajando. No hagas las cosas más difíciles o más complejas por el simple hecho de hacerlo.

+3

Si escribir una etiqueta JSP para cada método no es una sobreingeniería, entonces no sé qué es la sobreingeniería. No estoy diciendo que la opción n. ° 3 sea buena/preferida, pero tampoco la n. ° 2. – mindas

+0

Bueno, si tiene muchas instancias en las que tiene que invocar explícitamente métodos en su JSP: s, entonces le sugiero que mejore su patrón MVC y se esfuerce por crear una capa de Modelo más limpia que solo contenga datos. Luego mueve cualquier lógica a tu capa de Controlador. – pap

+0

El objeto myVar es un ejemplo exacto de lo que usted llama Modelo (objeto que solo contiene datos - datos de persistencia en este caso). Sin embargo, los datos que necesito visualizar provienen de fuentes completamente diferentes ("' anotherObject' ") y requieren esta clase de modelo. Su sugerencia de mover la lógica a la capa de controlador está cerca de la opción n. ° 3, que sugerí y dijo que era una mala idea. – mindas

1

¿Por qué no simplemente compones tu lista de objetos en tu código back-end Java y luego usas JSP para mostrarla?

+0

No creo que haya entendido el problema al que me enfrentaba. '$ {myVars}' ya se refiere a una lista de objetos. – mindas

0

Otra opción es usar Velocity. Es mucho mejor que jstl.

+1

Vote por una alternativa creativa (y una preferida por mí personalmente) pero, una vez más, no siempre podemos elegir cómo se nos permite mostrar vistas – darkpbj

7

Un simple de Java sólo "truco-fix" que funciona en la versión más antigua JSTL, también, y no requiere Taglibs/config/Dependencias/marcos adicionales, etc. es de "envolver" la función que desea llame desde JSTL en una clase que se extiende desde una clase Map y anule su método get().

Como un ejemplo mínimo, si p. desee llamar a la función Math.sin() de JSTL, debe definir una clase:

public class Sine extends HashMap<Double, Double> { 
    private static final long serialVersionUID = 1L; // Avoids compiler-warning 

    @Override 
    public Double get(Object arg) { 
     Double x = (Double) arg; 
     return Math.sin(x); 
    } 
} 

Luego, en su acción método execute(), que hace:

... 
request.setAttribute("sine", new Sine()); 
... 

Luego, en JSP se puede decir:

${sine[0.75]} 

para calcular el valor Math.sin(0.75)

JSTL tratará el seno variable como Map, pero puede calcular y devolver todo lo que quiera del método get().

supongo que se hace un poco más complicado si usted tiene más de un argumento a su función, pero no debe haber soluciones para que, también :)

+1

Enfoque interesante, ¡gracias por compartir! – mindas

+1

Tan bueno y complicado, muchas gracias. para aquellos que son nuevos en estos productos modelAndView.addObject ("sine", new Sine()); es equivalente a la versión MVC de spring de request.setAttribute ("sine", new Sine()); – HaMi

1

quería añadir un comentario a la última (por el tiempo) respuesta de Rop, pero falta "reputación", así que aquí estoy con una respuesta.

En breve tuve la misma idea con un mapa de este tipo, pero traté de hacerlo más general utilizable, con una "DynamicMap", interfaz DynamicMapCalculator y que permite ajustar cualquier llamada a dicho mapa (sin la necesidad de hacer un nueva implementación de mapas todo el tiempo, solo usando instanciación de clase anónima).

Este sería el tema, si está interesado: A qu. of style: dynamic map JSTL hack to work around missing parameter function calls

y yo estaría interesado en las opiniones allí: esto es algo que puede prescindir de una mala conciencia?

Cuestiones relacionadas