如何拦截 JSF 视图解析以替换结果页面?
How to intercept JSF view resolving in order to replace the outcome page?
某个托管 bean 具有 returns "/private/myview.jsf"
的操作方法。但是,不更改此代码,我想执行一些检查并最终呈现视图 "/private/other/myview.jsf"
。
所以,总而言之,我想在某处翻译"/private/myview.jsf"
到"/private/other/myview.jsf"
方法return和在实际视图渲染之前。
如何实现?
环境:
- 日蚀月神
- Java1.7
- JSF 2
现状
Web 应用程序完全可用,但未开发以支持辅助功能。
下一版本的要求
成为一个足够优秀的应用程序,供使用屏幕的盲人使用 readers。
详情
经过一番研究,我们得出的结论是,我们现在必须拥有每个页面的无障碍版本。
我们会为每个页面设计这样的无障碍版本,问题是什么时候显示无障碍版本,什么时候显示无障碍版本。
我们决定当用户单击顶部的某个 link 时,应用程序将转为 可访问模式 (这将不是默认状态)页。在可访问模式下,仅呈现可访问版本的页面。
我们不想审查所有的应用程序,我们想要的是拦截 JSF 的某些阶段并替换应该呈现的结果。例如,考虑以下内容:
- 某个页面有一个 link 或另一个页面的按钮,比方说
"mysettings.xhtml"
;
- 在可访问模式下,我们想告诉 JSF 不要渲染
"mysettings.xhtml"
,而是应该渲染 "mysettings_ac.xhtml"
或 "accessible/mysettings.xhtml"
;
- 这两个页面将与完全相同的托管 bean 进行交互,并将提供完全相同的功能,但一个对那些可以看到的人来说很好,另一个将被设计为易于屏幕显示 reader用户。
提前致谢!
So, in summary, I want to translate "/private/myview.jsf"
to "/private/other/myview.jsf"
somewhere after the method return and before the actual view rendering.
如果您已经在使用 JSF 2.2,则可以根据某些条件提供自定义 ResourceHandeler
wherein you return the desired view resource in 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
}
操作后有条件重定向return;我们可以在 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>
在第二种选择中,您可以在 ApplicationScope 中放置托管 bean,以便跨多个 JSF 页面使用。
虽然这些解决方案来自于一般概念,但不一定属于"somewhere after the method return and before the actual view rendering.",但你可以检查它是否解决了目的。
某个托管 bean 具有 returns "/private/myview.jsf"
的操作方法。但是,不更改此代码,我想执行一些检查并最终呈现视图 "/private/other/myview.jsf"
。
所以,总而言之,我想在某处翻译"/private/myview.jsf"
到"/private/other/myview.jsf"
方法return和在实际视图渲染之前。
如何实现?
环境:
- 日蚀月神
- Java1.7
- JSF 2
现状
Web 应用程序完全可用,但未开发以支持辅助功能。
下一版本的要求
成为一个足够优秀的应用程序,供使用屏幕的盲人使用 readers。
详情
经过一番研究,我们得出的结论是,我们现在必须拥有每个页面的无障碍版本。
我们会为每个页面设计这样的无障碍版本,问题是什么时候显示无障碍版本,什么时候显示无障碍版本。
我们决定当用户单击顶部的某个 link 时,应用程序将转为 可访问模式 (这将不是默认状态)页。在可访问模式下,仅呈现可访问版本的页面。
我们不想审查所有的应用程序,我们想要的是拦截 JSF 的某些阶段并替换应该呈现的结果。例如,考虑以下内容:
- 某个页面有一个 link 或另一个页面的按钮,比方说
"mysettings.xhtml"
; - 在可访问模式下,我们想告诉 JSF 不要渲染
"mysettings.xhtml"
,而是应该渲染"mysettings_ac.xhtml"
或"accessible/mysettings.xhtml"
; - 这两个页面将与完全相同的托管 bean 进行交互,并将提供完全相同的功能,但一个对那些可以看到的人来说很好,另一个将被设计为易于屏幕显示 reader用户。
提前致谢!
So, in summary, I want to translate
"/private/myview.jsf"
to"/private/other/myview.jsf"
somewhere after the method return and before the actual view rendering.
如果您已经在使用 JSF 2.2,则可以根据某些条件提供自定义 ResourceHandeler
wherein you return the desired view resource in 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 }
操作后有条件重定向return;我们可以在 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>
在第二种选择中,您可以在 ApplicationScope 中放置托管 bean,以便跨多个 JSF 页面使用。
虽然这些解决方案来自于一般概念,但不一定属于"somewhere after the method return and before the actual view rendering.",但你可以检查它是否解决了目的。