使用errorpage处理程序捕获hibernate异常?

时间:2012-03-25 02:18:16

标签: java hibernate jsf

我正在捕捉所有例外情况:              java.lang.Throwable中         /page.xhtml                   java.lang.Error的         /page.xhtml     

但是,如果我得到例如一个休眠的ex: org.hibernate.exception.ConstraintViolationException

我是否必须为每个可能发生的异常定义错误页面?我不能只说“抓住每一个例外”吗?

更新

重定向404工作。但是对于一个扔掉的人不会!

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.jsf</url-pattern>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.xhtml</location>
</error-page>
<error-page>
    <error-code>404</error-code>
    <location>/error.xhtml</location>
</error-page>

2 个答案:

答案 0 :(得分:1)

有一种更好的方法来处理JSF中的异常 - 通过自定义异常处理程序,可以在faces-config.xml中设置:

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
              version="2.0">
  <factory>
    <exception-handler-factory>com.mycompany.CustomExceptionHandlerFactory</exception-handler-factory>
  </factory>
</faces-config>

在这种情况下,您可以检查异常,它是根本原因并执行您想要的任何操作,因为您始终可以使用FacesContext。以下是如何处理恼人的ViewExpiredException

的示例

厂:

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {
  private ExceptionHandlerFactory parent;

  public CustomExceptionHandlerFactory(ExceptionHandlerFactory parent) {
    this.parent = parent;
  }

  @Override
  public ExceptionHandler getExceptionHandler() {
    return new CustomExceptionHandler(parent.getExceptionHandler());
  }
}

处理程序:

public class CustomExceptionHandler extends ExceptionHandlerWrapper {
  private ExceptionHandler wrapped;

  public CustomExceptionHandler(ExceptionHandler wrapped) {
    this.wrapped = wrapped;
  }

  @Override
  public ExceptionHandler getWrapped() {
    return wrapped;
  }

  @Override
  public void handle() throws FacesException {
    Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator();
    while (i.hasNext()) {
      ExceptionQueuedEvent event = i.next();
      ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
      Throwable t = context.getException();
      FacesContext fc = context.getContext();
      boolean exceptionHandled = handleException(t, fc);
      if(exceptionHandled) i.remove(); // remove from queue
    }
    getWrapped().handle(); // let wrapped ExceptionHandler do the rest
  }

  private boolean handleException(Throwable t, FacesContext fc) {
    if (t instanceof ViewExpiredException) {
      try {
        fc.getExternalContext().redirect("/expired/url/");
        return true;
      } catch (IOException e) {
        throw new FacesException(e);
      }
    } else return false;
  }
}

答案 1 :(得分:0)

java.lang.Throwable类是Java异常类层次结构中所有类的最不常见的祖先。所有异常和错误类都直接或间接地扩展Throwable

如果您有Throwable的错误页面,那么任何没有更具体错误页面的异常都会在那里结束。

因此,您的问题的答案是“否”。如果你想(你认为合适的任何粒度),你可以单独处理Hibernate异常,但你不需要。


<强>更新

异常不会产生错误页面的原因有很多种。例如,它们可能在重定向处理期间发生,或者它们可能被过滤器捕获。或者他们可能会在提交响应标头之后被抛出;例如如果在格式化响应HTML期间发生异常。

(一个突出的线索是,当你抛出异常时,你是否正在任何错误页面。如果你得到一个'500'错误页面,那么某些东西正在发生。如果没有,那么你可能处于阻止任何错误页面生成的情况之一。)

无论如何,这是Servlet规范(3.0版)所说的。仔细阅读。


10.9.2错误页面

  

允许开发人员自定义返回给Web客户端的内容的外观   当servlet生成错误时,部署描述符定义错误列表   页面描述。语法允许返回资源的配置   当servlet或过滤器对响应调用sendError时的容器   特定的状态代码,或者servlet是否生成传播的异常或错误   到容器。

     

如果在响应上调用了sendError方法,则容器会查询列表   使用状态代码语法的Web应用程序的错误页面声明   尝试比赛。如果匹配,容器将返回指示的资源   通过位置输入。

     

servlet或过滤器在处理过程中可能会抛出以下异常   请求:

     
      
  • 运行时异常或错误
  •   
  • ServletExceptions或其子类
  •   
  • IOExceptions或其子类
  •   
     

Web应用程序可能使用异常类型声明了错误页面   元件。在这种情况下,容器通过比较来匹配异常类型   使用异常类型的错误页面定义列表抛出异常   元件。匹配导致容器返回指示的资源   位置输入。类层次结构中最接近的匹配获胜。

     

如果没有包含异常类型的错误页面声明适合使用该类 -   层次结构匹配,抛出的异常是ServletException或子类   其中,容器提取包装的异常,如由其定义的   ServletException.getRootCause方法。对错误进行第二次传递   页面声明,再次尝试匹配错误页面声明,   但改为使用包装的异常。

     

在部署中使用exception-type元素的错误页面声明   描述符必须是唯一的,直到异常类型的类名。同样的,   使用status-code元素的错误页面声明必须是唯一的   部署描述符,直到状态码。

     

描述的错误页面机制在发生错误时不会介入   使用RequestDispatcher或filter.doFilter方法调用。这样,一个   使用RequestDispatcher的过滤器或servlet有机会处理错误   生成。

     

如果servlet生成错误页面机制未处理的错误,则为   如上所述,容器必须确保发送状态为500的响应。   默认的servlet和容器将使用sendError方法发送4xx和   5xx状态响应,以便可以调用错误机制。默认   servlet和容器将使用setStatus方法进行2xx和3xx响应   不会调用错误页面机制。

     

如果应用程序正在使用第2.3.3.3节中描述的异步操作,   第2-10页的“异步处理”,应用程序负责   处理应用程序创建的线程中的所有错容器可以照顾   来自AsyncContext.start发出的线程的错误。用于处理错误   在AsyncContext.dispatch期间发生,请参见第n节“任何错误或异常   在执行调度方法期间可能发生的事情必须被捕获   由容器处理如下:“第2-16页