某个托管bean有一个返回"/private/myview.jsf"
的操作方法。但是,在不更改此代码的情况下,我希望执行一些检查并最终呈现视图"/private/other/myview.jsf"
。
因此,总的来说,我想在方法返回后的和实际视图渲染前的<strong]处将"/private/myview.jsf"
转换为"/private/other/myview.jsf"
。>
如何做到这一点?
环境:
- Eclipse Luna
- Java 1.7
- JSF 2
当前条件
Web应用程序完全可操作,但不是为支持可访问性功能而开发的。
下一版本的要求
成为一个足够好的应用程序,供使用屏幕阅读器的盲人使用。
详细信息
经过一番研究,我们得出的结论是,我们现在必须为每个页面提供一个可访问的版本。
我们将为每个页面设计这样的可访问版本,问题是何时显示不可访问版本以及何时显示可访问版本。
我们决定,当用户单击页面顶部的某个链接时,应用程序将转到可访问模式(这不是默认状态)。在可访问模式下,仅呈现页面的可访问版本。
我们不想审查所有的应用程序,我们想要的是截取JSF的某个阶段,并替换应该呈现的结果。例如,考虑以下内容:
- 某个页面有指向另一个页面的链接或按钮,比如
"mysettings.xhtml"
- 当处于可访问模式时,我们想告诉JSF不要渲染
"mysettings.xhtml"
,而应该渲染"mysettings_ac.xhtml"
或"accessible/mysettings.xhtml"
- 两个页面都将与相同的托管bean进行交互,并将提供相同的功能,但其中一个页面对能够看到的用户很好,另一个页面的设计将使屏幕阅读器用户感到舒适
提前感谢!
因此,总之,我想在方法返回后的和实际视图渲染前的某处将
"/private/myview.jsf"
转换为"/private/other/myview.jsf"
如果您已经使用JSF 2.2,您可以通过提供自定义ResourceHandeler
来实现这一点,其中您可以根据某些条件在createViewResource()
中返回所需的视图资源。
public class YourResourceHandler extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
public YourResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public ViewResource createViewResource(FacesContext context, final String name) {
if (someCondition) {
name = name.replace("/private/", "/private/other/");
}
return super.createViewResource(context, name);
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
其在faces-config.xml
中注册如下:
<application>
<resource-handler>com.example.YourResourceHandler</resource-handler>
</application>
或者,如果您还没有使用JSF 2.2,那么请使用ResourceResolver
。
public class YourResourceResolver extends ResourceResolver {
private ResourceResolver parent;
public YourResourceResolver(ResourceResolver parent) {
this.parent = parent;
}
@Override
public URL resolveUrl(String path) {
if (someCondition) {
path = path.replace("/private/", "/private/other/");
}
return parent.resolveUrl(path);
}
}
其在web.xml
中注册如下:
<context-param>
<param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
<param-value>com.example.YourResourceResolver</param-value>
</context-param>
正如我所看到的,有两种可能的解决方案
-
使用
redirect()
方法returnAction(){ ExternalContext context = FacesContext.getCurrentInstance().getExternalContext(); context.redirect("/private/other/myview.jsf"); //Relative path might vary based upon your business logic }
-
动作返回后的条件重定向;我们可以在faces-config.xml中维护一个导航规则,如下所示:
<navigation-rule>
<navigation-case>
<from-action>#{yourManagedBean.actionMethod}</from-action>
<if>#{yourManagedBean.redirectAccessibleFlag}</if> <!-- We maintain a boolean variable redirectAccessibleFlag in the managed Bean and set its value to true or false conditionally-->
<to-view-id>/private/other/myview.jsf</to-view-id>
<redirect/>
</navigation-case>
</navigation-rule>
在第二种选择中,您可以将托管bean放在ApplicationScope中,以便在多个JSF页面中使用。
尽管这些解决方案来自一般概念,但它们可能不一定属于"方法返回后的某个地方和实际视图渲染前的某个。"但您可以检查它是否解决了目的。