¿Cómo navegar en JSF? Cómo hacer que la URL refleje la página actual (y no la anterior)
Actualmente estoy aprendiendo JSF y quedé bastante sorprendido y desconcertado cuando me di cuenta de que cada vez que usamos <h:form>
, el comportamiento estándar de JSF es mostrarme siempre la URL de la página anterior en el navegador, en lugar de la URL de la página actual .
Entiendo que esto tiene que ver con la forma en que JSF siempre publica un formulario en la misma página y luego simplemente muestra cualquier página que el controlador le devuelve al navegador, que no sabe que la ubicación de la página ha cambiado.
Parece que JSF existe desde hace suficiente tiempo como para que deba haber una forma limpia y sólida de abordar esto. Si es así, ¿te importaría compartirlo?
He encontrado varias soluciones, pero lamentablemente ninguna que parezca una solución realmente sólida.
- Simplemente acepte que la URL es engañosa.
- Agregue
"?faces-redirect=true"
al valor de retorno de la acción de cada bean y luego- descubra cómo reemplazarlo
@RequestScoped
con otra cosa (Flash Scopes, conversación CDI, @SessionScoped, ...). - Acepte tener dos viajes de ida y vuelta HTTP para cada acción del usuario.
- descubra cómo reemplazarlo
- Utilice algún método (por ejemplo, una biblioteca de terceros o un código personalizado) para ocultar el nombre de la página en la URL, utilizando siempre la misma URL genérica para cada página.
Si "?faces-redirect=true"
es tan bueno como parece, ¿hay alguna manera de configurar una aplicación completa para tratar todas las solicitudes de esta manera?
De hecho, JSF, al ser una aplicación basada en formularios dirigida al marco MVC, envía el formulario POST a la misma URL donde <h:form>
se solicitó la página con el formulario. Puede confirmarlo mirando la <form action>
URL del resultado HTML generado. En términos de desarrollo web, esto se caracteriza como devolución de datos . De forma predeterminada, una navegación en una devolución de datos no genera una nueva solicitud a la nueva URL, sino que carga la página de destino como contenido de la respuesta. De hecho, esto es confuso cuando simplemente desea navegación de página a página.
Generalmente, el enfoque correcto en cuanto a navegación/redireccionamiento depende de los requisitos comerciales y de la idempotencia (léase: "marcable") de la solicitud (nota: para ejemplos de código concretos, consulte los enlaces "Ver también" a continuación).
Si la solicitud es idempotente, simplemente use un formulario/enlace GET en lugar del formulario POST (es decir, use ,
<a>
o en lugar de y ). Por ejemplo, navegación de página a página, formulario de búsqueda similar a Google, etc.<form>
<h:link>
<h:button>
<h:form>
<h:commandXxx>
Si la solicitud no es idempotente, simplemente muestre los resultados de forma condicional en la misma vista (es decir, devuelva
null
ovoid
desde el método de acción y utilice, por ejemplo,<h:message(s)>
y/orendered
).
Por ejemplo, entrada/edición de datos en la página, asistente de varios pasos, diálogo modal, formulario de confirmación, etc.Si la solicitud no es idempotente, pero la página de destino es idempotente, simplemente envíe una redirección después de la POST (es decir, devuelva el resultado con el
?faces-redirect=true
método de acción, o invoque manualmenteExternalContext#redirect()
o coloque<redirect/>
en el caso de navegación XML heredado).
Por ejemplo, mostrar una lista de todos los datos después de una edición exitosa, redirigir después de iniciar sesión, etc.
Tenga en cuenta que la navegación pura de página a página suele ser idempotente y aquí es donde muchos iniciadores de JSF fallan al abusar de los enlaces/botones de comando para eso y luego se quejan de que las URL no cambian. También tenga en cuenta que los casos de navegación rara vez se utilizan en aplicaciones del mundo real desarrolladas con respecto a SEO/UX y aquí es donde muchos tutoriales de JSF fallan al permitir que los lectores crean lo contrario.
También tenga en cuenta que usar POST no es en absoluto "más seguro" que GET porque los parámetros de solicitud no son visibles inmediatamente en la URL. Todavía son visibles en el cuerpo de la solicitud HTTP y aún son manipulables. Por lo tanto, no hay absolutamente ninguna razón para preferir POST para solicitudes idempotentes por motivos de "seguridad". La verdadera seguridad está en usar HTTPS en lugar de HTTP y verificar los métodos de servicios comerciales si el usuario actualmente conectado puede consultar la entidad X, o manipular la entidad X, etc. Un marco de seguridad decente ofrece anotaciones para esto.
Ver también:
- ¿Cuál es la diferencia entre redireccionamiento y navegación/reenvío y cuándo usar qué?
- Navegación JSF implícita versus explícita
- Qué URL usar para vincular/navegar a otras páginas JSF
- Capacidad de marcadores a través de la función Ver parámetros
- ¿Para qué se pueden utilizar <f:metadata>, <f:viewParam> y <f:viewAction>?
- ¿Cuándo debo utilizar h:outputLink en lugar de h:commandLink?
- Crear páginas maestras y de detalles para entidades, cómo vincularlas y qué alcance de bean elegir
- Conservar los parámetros de cadena de consulta de solicitud GET en el envío del formulario JSF
- Pasar un objeto entre beans @ViewScoped sin usar parámetros GET