JSF中Exception的处理<o:p></o:p>
环境: myfaces1.1.5,richfaces1.3,Websphere6.1
目标:
统一处理应用中的Exception,解析其中的错误信息,使用Globalization 来显示消息。
分析:
JSF中有两类error,一类是input error,是由用户输入错误的信息造成的,一般在input 验证或者转化过程中会出现;另一类是application error,是系统中可能出现的各种错误,如SQLException、NullPointerException等。对于application error,在系统中会统一抛出AppException,然后由我们自己订制的ActionListener处理;而对于input error,则由JSF处理。下面详细讨论如何处理application Error.
思路:将Exception转化为Faces Message处理。
在系统中我们采用两种策略共同处理Exception。即当JSF请求处理中出现Exception时,采取第一种策略,在这个页面上显示一条消息提示用户;当非JSF请求出现Exception时,将这个Exception抛给Web Container,并将页面导航到某一个错误页面。。
<o:p> </o:p>
实现:<o:p></o:p>
下面分别讨论这两种策略如何实现。<o:p></o:p>
第一种,JSF请求,弹出提示消息。<o:p></o:p>
在我们的系统中,综合使用Exception 和 FacesMessage来综合处理Exception,当Exception抛出时,尤其是Business Exception发生时,这个Exception是发生在JSF的InvokeAppication Phase,因此通过订制ActionListener就捕获这个Exception,并将这个Exception转化为FacesMessage,并根据Exception的Message到资源文件中加载对应的国际化。
当ActionListen无法捕获这个Exception时,将这个错误发送到WebContainer,并转向error页面。这时,对于这个请求的响应会产生500等Error Code并发送到客户端。
因此,首先要定制JSF的ActionListener,在其上添加以下方法:<o:p></o:p>
try {<o:p></o:p>
outcome = (String) methodBinding.invoke(facesContext, null);<o:p></o:p>
} catch (Exception e) {<o:p></o:p>
Throwable cause = e.getCause();<o:p></o:p>
if (cause != null && cause instanceof AbortProcessingException) {<o:p></o:p>
throw (AbortProcessingException) cause;<o:p></o:p>
} else {<o:p></o:p>
Exception ex = (Exception) e.getCause();<o:p></o:p>
String message = ex.getMessage();<o:p></o:p>
//get localized Message string from resource bundle <o:p></o:p>
String localizedMessage = getBundleMessage(message);<o:p></o:p>
if (null != localizedMessage && "".equals(localizedMessage)) {<o:p></o:p>
throwNewFacesMessage(actionEvent.getComponent()<o:p></o:p>
.getClientId(facesContext), localizedMessage,<o:p></o:p>
FacesMessage.SEVERITY_ERROR);<o:p></o:p>
} else {<o:p></o:p>
throwNewFacesMessage(actionEvent.getComponent()<o:p></o:p>
.getClientId(facesContext), message,<o:p></o:p>
FacesMessage.SEVERITY_ERROR);<o:p></o:p>
}<o:p></o:p>
}// org.apache.myfaces.application.ActionListenerImpl
在上面的方法中拦截所有的Exception,并转化为FacesMessage,这样JSF会直接转向Render Phase,从而停止Application method的进一步处理,实现Exception的handler。<o:p></o:p>
其次,在页面上添加<h:messages></h:messages>标识,就可以显示所有的错误消息。<o:p></o:p>
再者,覆盖A4J.AJAX.onError,由于我们在系统中还采用了Richfaces,Richfaces在判断Ajax请求在服务器的处理出现错误后,会有一个默认的处理函数A4J.AJAX.onError。这样当服务器端发送500等Error Code时,就可以被客户端的Ajax感知,并添加处理:<o:p></o:p>
A4J.AJAX.onError = function(req,status,message) {
var report = "An error has occurred during the request,Message is: " + message;
if(Ext.MessageBox.show){
Ext.MessageBox.show({
title: 'Error Report',
msg: report,
width:400,
buttons: Ext.MessageBox.OK
});
}else{
alert(report);
}
<o:p> </o:p>
};<o:p></o:p>
第二种,非Ajax请求,跳转到错误页面。可以通过配置web.xml来实现:<o:p></o:p>
<error-page>
<exception-type>javax.faces.FacesException<!---->exception-type>
<location>/error.jsp<!---->location>
<!---->error-page>
<error-page>
<error-code>500<!---->error-code>
<location>/error.jsp<!---->location>
<!---->error-page><o:p></o:p>
这样,当产生错误时,就会转向这个页面。<o:p></o:p>