[英]How to work with application modes in JSF
My application (JSF 2, Java 6, JBoss 7.1) has to offer two operating modes: accessibility mode and non-accessibility mode. 我的应用程序(JSF 2,Java 6,JBoss 7.1)必须提供两种操作模式:可访问性模式和非可访问性模式。
In accessibility mode, some (not all) pages have a particular design to be better read by a screen reader. 在可访问性模式中,一些(并非所有)页面具有特定设计以便屏幕阅读器更好地读取。 The difference between the two modes is purely visual, the managed beans are precisely the same.
两种模式之间的区别纯粹是视觉上的,托管bean完全相同。 Ideally, no Java code has to be changed.
理想情况下,不需要更改Java代码。
Most of the work is done: 大部分工作已经完成:
With all that, it works almost perfectly, but it seems there is some kind of view cache that breaks my solution. 尽管如此,它几乎完美地工作,但似乎有某种视图缓存会破坏我的解决方案。 Consider the scenario below:
考虑以下场景:
In the last step we can understand that, even in accessibility mode and with the resource path translation happening (I have logs to proof), the pages are generated as they were in the default, non-accessibility mode. 在最后一步中,我们可以理解,即使在可访问性模式中并且发生资源路径转换(我有记录到证明),页面也会以默认的非可访问性模式生成。
So, is really there a pages cache in JSF? 那么,JSF中真的有页面缓存吗? How can I clear it, so the pages will indeed be rendered again?
我怎样才能清除它,所以页面确实会再次渲染?
A network monitoring showed me that the request is indeed issued to the application, so no browser cache is playing here. 网络监控向我显示该请求确实已发布到应用程序,因此此处没有浏览器缓存。
After some time I could finally find a solution, which means, a coding strategy that satisfies all the requirements I had. 过了一段时间,我终于可以找到一个解决方案,这意味着一个满足我所有要求的编码策略。 Maybe it's not a technically good solution, but it is a functinal solution in the sense it produces the experience I needed to provide, saving me to touch all already existing my Java code.
也许这不是一个技术上很好的解决方案,但它是一个功能上的解决方案,因为它产生了我需要提供的体验,使我能够触及所有现有的Java代码。 There it goes!
它去了!
The managed bean below is responsible to turn the accessibility on and off in response to the users click on a certain command link. 下面的托管bean负责响应用户点击某个命令链接来打开和关闭可访问性。 The idea is to add an attribute to the session when the accessibility mode is turned on and remove it when the accessibility mode is turned off.
这个想法是在打开辅助功能模式时向会话添加属性,并在关闭辅助功能模式时将其删除。
Those actions return a redirection the current page so the user immedially sees the interface changing from one mode to the other. 这些操作返回当前页面的重定向,因此用户可以立即看到界面从一种模式变为另一种模式。
When the accessibility is turned on, the view path is changed to append a /ac
, because all my accessible views have the same file name that the non-accessibility ones, but in a subdirectory named ac
. 启用辅助功能后,视图路径将更改为附加
/ac
,因为我的所有可访问视图都具有与不可访问视图相同的文件名,但位于名为ac
的子目录中。
@ManagedBean
@RequestScoped
public class AccessibilityMB {
private boolean accessibilityOn = false;
@PostConstruct
public void init() {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
if(session!=null) {
Boolean accessibilityMode = (Boolean)session.getAttribute("AccessibilityMode");
accessibilityOn = accessibilityMode!=null && accessibilityMode;
}
}
public String turnAccessibilityOff() {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
if(session!=null) {
session.setAttribute("AccessibilityMode", accessibilityOn = true);
}
String viewId = context.getViewRoot().getViewId();
return viewId+"?faces-redirect=true";
}
public String turnAccessibilityOn() {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
if(session!=null) {
accessibilityOn = false;
session.removeAttribute("AccessibilityMode");
}
String viewId = context.getViewRoot().getViewId();
int index = viewId.lastIndexOf("/ac/");
if(index>-1)
viewId = viewId.substring(0, index)+viewId.substring(index+3);
return viewId+"?faces-redirect=true";
}
public boolean getAccessibilityOn() {
return accessibilityOn;
}
}
The PhaseListener just checks for the accessibility mode and, in such a circunstance, rewrites the path the view to look for in the ac
subdirectoty. PhaseListener只检查辅助功能模式,并在这种情况下,重写在
ac
子目录中查找的视图的路径。 If the desided view exists there, the current component tree is discarded and rebuilt from the accessible version of the same view. 如果存在desided视图,则丢弃当前组件树并从同一视图的可访问版本重建。
Here the solution is not so good, because JSF already worked to build a component tree and I'm simply discarding it to reworking it from another file. 这里的解决方案并不是那么好,因为JSF已经在构建一个组件树,而我只是放弃它来从另一个文件重新编写它。
public class AccessibilityPhaseListener implements PhaseListener{
private static final long serialVersionUID = 1L;
@Override
public void beforePhase(PhaseEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
if(session==null) {
return;
}
Boolean acessibilityMode = (Boolean)session.getAttribute("AcessibilityMode");
if(acessibilityMode==null || !acessibilityMode)
return;
String viewId = context.getViewRoot().getViewId();
if(acessibilityMode) {
int index = viewId.lastIndexOf("/");
viewId = viewId.substring(0, index+1)+"ac/"+viewId.substring(index+1);
} else {
int index = viewId.lastIndexOf("/");
if(viewId.substring(index-3, index).equals("/ac"))
viewId = viewId.substring(0, index-3)+viewId.substring(index);
}
URL url = null;
try {
url = context.getExternalContext().getResource(viewId);
} catch (MalformedURLException e) {
}
if(url==null)
return;
ViewHandler handler = context.getApplication().getViewHandler();
UIViewRoot root = handler.createView(context, viewId);
root.setViewId(viewId);
context.setViewRoot(root);
}
@Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
}
I could satisfy all my requirements: 我可以满足我的所有要求:
I undestand that this solution works with any kind of application modes, not only accessibility. 我不认为这个解决方案适用于任何类型的应用程序模式,而不仅仅是可访问性。 Any time someone needs to select a certain view instead of the other based on an application or session parameter, it will work.
任何时候有人需要根据应用程序或会话参数选择某个视图而不是另一个视图,它将起作用。 For instance, a multiculture application where the culture customization goes futher than color and language, requiring a complete redesign of views can take advantage of this model.
例如,多文化应用程序,其中文化定制比颜色和语言更进一步,需要完全重新设计视图可以利用此模型。
The downside of all this is the fact that, when the accessibility mode is on and there is an accessible version of a certain view, JSF will work twice, one time to build the original view and a second time to build the accessible version. 所有这些的缺点是,当可访问性模式打开并且存在特定视图的可访问版本时,JSF将工作两次,一次构建原始视图,第二次构建可访问版本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.