2011-07-25 42 views
85

Empecé a usar JSF 2.0 con Facelets recientemente y me desconcertaron los nuevos componentes compuestos que conocen el existente <ui:include> y otras técnicas de creación de plantillas que ofrece Facelets 1.x.Cuándo utilizar <ui:include>, archivos de etiquetas, componentes compuestos y/o componentes personalizados?

¿Cuál es la diferencia entre esos enfoques? Funcionalmente parecen ofrecer casi lo mismo: <ui:param> frente a <cc:attribute>, <ui:insert> + <ui:define> frente a los archivos de etiquetas, la reutilización de las plantillas existentes. ¿Hay algo más que la sintaxis y la especificación de interfaz clara en el caso de componentes compuestos? ¿Podría el rendimiento diferir?

Respuesta

152

¿Cuál es la diferencia entre esos enfoques?

plantillas facelet

plantillas de Uso facelet (como en <ui:composition>, <ui:include> y <ui:decorate>) si desea dividir fragmentos principales de diseño de página en plantillas reutilizables. P.ej. cabecera, menú, el contenido, pie de página, etc.

Ejemplos:

Archivos de etiquetas de facelet

Utilice los archivos de etiquetas de Facelet si desea tener un grupo reutilizable de componentes para evitar/minimizar la duplicación de código. P.ej. un grupo de componentes label + input + message. La principal diferencia con los componentes compuestos es que la salida de un archivo de etiqueta de Facelet no representa un solo UIComponent y, en algunas circunstancias, puede ser la única solución cuando un componente compuesto no es suficiente. En general, tener un <ui:include> con uno o más <ui:param> es una señal de que el archivo incluido puede ser mejor un archivo de etiqueta.

Ejemplos:

componentes compuestos

utilizar C Componentes opuestos si desea crear un único y reutilizable UIComponent personalizado con una sola responsabilidad usando XML puro. Tal componente compuesto por lo general consiste en un conjunto de componentes existentes y/o HTML y se procesa físicamente como un solo componente y se supone que está ligado a una única propiedad de bean. P.ej.un componente que representa una sola propiedad java.util.Date por 3 componentes <h:selectOneMenu> dependientes, o un componente que combina <p:fileUpload> y <p:imageCropper> en un solo <my:uploadAndCropImage> que hace referencia a una única entidad personalizada com.example.Image como propiedad.

Ejemplos:

componentes personalizados

Utilice un componente personalizado cada vez que la funcionalidad no se puede lograr con archivos de etiquetas facelet o componentes compuestos, debido a la falta de apoyo en la norma/disponible conjunto de componentes. Se pueden encontrar ejemplos sobre todos los lugares en el código fuente de bibliotecas de componentes de código abierto tales como PrimeFaces y OmniFaces.

controladores de etiquetas

Cuando se desea controlar la construcción del árbol de componentes JSF en lugar de prestación de la salida HTML, entonces usted debe utilizar un controlador de etiqueta en lugar de un componente.

Ejemplos:

Ejemplo proyectos

Aquí están s Algunos proyectos de ejemplo que utilizan todas las técnicas mencionadas anteriormente.


podrían diferir rendimiento?

Técnicamente, la preocupación por el rendimiento es insignificante. La elección debe hacerse en función de los requisitos funcionales concretos y el grado final de abstracción, reutilización y mantenimiento de la implementación. Cada enfoque tiene su propio propósito y limitaciones bien definidos.

Sin embargo, los componentes compilados tienen una sobrecarga significativa durante la construcción/restauración de la vista (específicamente: durante el guardado/restauración del estado de la vista). Y, en versiones anteriores de Mojarra, los componentes compuestos tenían problemas de rendimiento con la asignación de valores predeterminados, esto ya está solucionado desde 2.1.13. Además, Mojarra tenía un memory leak cuando se utiliza un <cc:attribute method-signature> para las expresiones de métodos, básicamente todo el árbol de componentes se vuelve a referenciar en la sesión HTTP, esto es fijo desde 2.1.29/2.2.8. La pérdida de memoria puede ser pasado por alto en la edad avanzada 2.1 versiones de la siguiente manera:

<context-param> 
    <param-name>com.sun.faces.serializeServerState</param-name> 
    <param-value>true</param-value> 
</context-param> 

O en edad avanzada 2.2 versiones como abajo:

<context-param> 
    <param-name>javax.faces.SERIALIZE_SERVER_STATE</param-name> 
    <param-value>true</param-value> 
</context-param> 

Sin embargo, cuando se tiene relativamente "una gran cantidad de" componentes compuestos, y tiene javax.faces.STATE_SAVING_METHOD establecido en client, entonces el rendimiento será un dolor. No abuse de los componentes compuestos si solo desea la funcionalidad básica que ya es posible con un simple archivo de inclusión o un archivo de etiqueta. No use la facilidad de configuración (léase: no se necesita el archivo *.taglib.xml) como excusa para preferir los componentes compuestos a los archivos de etiquetas.

Al utilizar Mojarra 2.2.10 o más, no se olvide de desactivar los Facelets período relativamente corto de actualización para el modo de producción:

<context-param> 
    <param-name>javax.faces.FACELETS_REFRESH_PERIOD</param-name> 
    <param-value>-1</param-value> 
</context-param> 

No utilice esta configuración para el desarrollo, de lo contrario usted tiene que reiniciar el todo el servidor para que se reflejen los cambios en los archivos Facelets Mojarra 2.2.11 y versiones posteriores, y MyFaces ya está predeterminado en -1 cuando javax.faces.PROJECT_STAGE no está configurado en Development.

+0

¿por qué le gustaría renderizar 1 componente (componente compuesto) en lugar de digamos 3 (archivo de etiqueta facelet)? Quiero decir, en un día soleado tal vez te sientas como 1 en lugar de 3 ... pero creo que hay algo más detrás de eso. En su ejemplo, está extendiendo UINamingContainer ... ¿podría ser esa una de las razones por las que debe buscar un cc (para poder sobrescribir algunas funciones específicas de la implementación de jsf)? – Toskan

+2

Un archivo de etiqueta debe verse como una especie de incluir. Un componente compuesto debe verse como un componente real. Un componente compuesto ** requiere ** para implementar 'NamingContainer', de lo contrario terminará con problemas de ID duplicados cuando el mismo componente se reutilice varias veces. – BalusC

+0

@BalusC Digamos que tengo un montón de HTML y JSF que crean un 'bloque' que me permite agregar o eliminar direcciones (y todos sus atributos: calle, número, ciudad, etc.). Necesito usar ese mismo bloque en 2 o 3 páginas. ¿Eso cae bajo su descripción de un componente compuesto? – RinaldoPJr

Cuestiones relacionadas