我会以另一种方式亲自实现它。
在您的faces-config.xml 中定义一个异常处理程序工厂,如下所示:
<factory>
<exception-handler-factory>
com.package.faces.FullAjaxExceptionHandlerFactory
</exception-handler-factory>
</factory>
创建扩展javax.faces.context.ExceptionHandlerFactory 的异常处理程序工厂。它应该返回您自己的 ExceptionHandler 实现。这可能是一个例子:
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;
public class FullAjaxExceptionHandlerFactory extends ExceptionHandlerFactory {
private ExceptionHandlerFactory wrapped;
/**
* Construct a new full ajax exception handler factory around the given wrapped factory.
* @param wrapped The wrapped factory.
*/
public FullAjaxExceptionHandlerFactory(ExceptionHandlerFactory wrapped) {
this.wrapped = wrapped;
}
/**
* Returns a new instance of {@link FullAjaxExceptionHandler} which wraps the original exception handler.
*/
@Override
public ExceptionHandler getExceptionHandler() {
return new FullAjaxExceptionHandler(wrapped.getExceptionHandler());
}
/**
* Returns the wrapped factory.
*/
@Override
public ExceptionHandlerFactory getWrapped() {
return wrapped;
}
}
最后,扩展javax.faces.context.ExceptionHandlerWrapper 来处理所有异常。一个例子如下:
public class FullAjaxExceptionHandler extends ExceptionHandlerWrapper {
private ExceptionHandler wrapped;
public FullAjaxExceptionHandler(ExceptionHandler wrapped) {
this.wrapped = wrapped;
}
private static Throwable extractCustomException(Throwable ex) {
Throwable t = ex;
while (t != null) {
if (t instanceof YourOwnExceptionInterface) {
return t;
}
t = t.getCause();
}
return ex;
}
private static String extractMessage(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
return matchJmillErrorTag(sw.toString());
}
public static boolean handleException(Throwable original) {
Throwable ex = extractCustomException(original);
if (ex instanceof ViewExpiredException) {
// redirect to login page
return false;
} else if (ex instanceof YourOwnExceptionInterface) {
((YourOwnExceptionInterface) ex).handle();
return true;
} else if (ex instanceof NonexistentConversationException) {
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
// redirect to login page
return false;
} else {
String message = extractMessage(ex);
final FacesContext fc = FacesContext.getCurrentInstance();
original.printStackTrace();
// redirect to error page
fc.responseComplete();
return true;
}
}
@Override
public void handle() throws FacesException {
final Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
FacesContext facesContext = FacesContext.getCurrentInstance();
if (Redirector.isRedirectingToLogin(facesContext)) {
return;
}
while (i.hasNext()) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
i.remove();
if (!handleException(context.getException())) {
return;
}
}
getWrapped().handle();
}
@Override
public ExceptionHandler getWrapped() {
return wrapped;
}
}
查看上一课的public static boolean handleException(Throwable original)。您可以使用它来管理所有异常。
有一次我在那里设置了一个关于YourOwnExceptionInterface 的条件,它是一个带有handle() 方法的接口,例如我将通过NotAuthorizedException 类型的异常来实现。在这种情况下,在NotAuthorizedException 的handle() 方法中,我会通知用户他无法通过p:growl 组件完成某个操作。我会在我的 bean 中使用它作为 throw new NotAuthorizedException("message");
自定义异常类当然应该扩展RuntimeException。