Ceci est une idée intéressante. Je serais curieux de savoir comment ça se passe en pratique.
Obtenir les règles de navigation
Navigation est assurée par le NavigationHandler. Obtenir le gestionnaire de navigation n'est pas difficile, mais l'API n'expose pas les règles qu'elle utilise.
Comme je le vois, vous pouvez:
- Parse faces-config.xml lors de l'initialisation et de stocker les règles dans le contexte d'application (facile)
- mettre en œuvre votre propre NavigationHandler qui ne tient pas compte des règles dans faces-config.xml ou les complète avec votre propre fichier de règles et expose son ensemble de règles en quelque sorte (réalisable, mais prend un peu de travail)
- mock votre propre FacesContext et passez-le au gestionnaire de navigation existant (vraiment difficile de faire l'objet de deux coexistent dans FacesContext même thread et extrêmement inefficace)
Maintenant, vous avez un autre problème aussi. Où allez-vous garder les cartographies pour rechercher les vues? Hard-code les dans les haricots?
En utilisant les règles de navigation
Off main, je peux penser à deux façons dont vous pouvez construire des URL contenant des paramètres de l'arrière-plan. Les deux impliquent la définition d'un haricot quelconque.
<managed-bean>
<managed-bean-name>navBean</managed-bean-name>
<managed-bean-class>foo.NavBean</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
Source:
package foo;
import java.io.IOException;
import java.io.Serializable;
import java.net.URLEncoder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
public class NavBean implements Serializable {
private String getView() {
String viewId = "/showMessage.faces"; // or look this up somewhere
return viewId;
}
/**
* Regular link to page
*/
public String getUrlLink() {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext extContext = context.getExternalContext();
String viewId = getView();
String navUrl = context.getExternalContext().encodeActionURL(
extContext.getRequestContextPath() + viewId);
return navUrl;
}
/**
* Just some value
*/
public String getValue() {
return "" + System.currentTimeMillis();
}
/**
* Invoked by action
*/
public String invokeRedirect() {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext extContext = context.getExternalContext();
String viewId = getView();
try {
String charEncoding = extContext.getRequestCharacterEncoding();
String name = URLEncoder.encode("foo", charEncoding);
String value = URLEncoder.encode(getValue(), charEncoding);
viewId = extContext.getRequestContextPath() + viewId + '?' + name
+ "=" + value;
String urlLink = context.getExternalContext().encodeActionURL(
viewId);
extContext.redirect(urlLink);
} catch (IOException e) {
extContext.log(getClass().getName() + ".invokeRedirect", e);
}
return null;
}
}
GET
Pour une requête GET, vous pouvez utiliser les UIParameters pour définir les valeurs et laisser le moteur de rendu construire la liste des paramètres.
<h:outputLink value="#{navBean.urlLink}">
<f:param name="foo" value="#{navBean.value}" />
<h:outputText value="get" />
</h:outputLink>
POST
Si vous souhaitez définir l'URL à vue au cours d'une action POST, vous pouvez le faire en utilisant une redirection dans une action (appelée par un bouton ou commandLink).
<h:commandLink id="myCommandLink" action="#{navBean.invokeRedirect}">
<h:outputText value="post" />
</h:commandLink>
Remarques
Notez que ExternalContext.encodeActionURL est utilisé pour coder la chaîne. C'est une bonne pratique pour produire du code portable dans tous les contextes (portlets, etcetera). Vous utiliseriez encodeResourceURL si vous étiez en train d'encoder un lien vers une image ou un fichier de téléchargement.
Notez que j'ai écrit cette réponse avant la sortie de JSF2/JEE6. JSF2 ajoute le support pour les paramètres d'affichage. Toute personne bloquée sur JSF1.2/JEE5 devrait envisager d'utiliser Seam. – McDowell