【问题标题】:Handling Exceptions like ServletRequestBindingException in Spring rather than Servlet Container在 Spring 中处理 ServletRequestBindingException 等异常而不是 Servlet Container
【发布时间】:2011-03-15 09:14:48
【问题描述】:

我将 springmvc 用于 REST 项目,并且每当客户端使用错误的 HTTP 方法调用 REST 资源时,都会引发 servletrequestbindingexception。我无法在控制器中使用 @ExceptionHandler 处理这些异常,因为它不是发生在处理程序方法中,而是发生在 spring 映射层中。

目前我声明了一个 web.xml 异常处理,这是可行的:

<error-page>
    <exception-type>org.springframework.web.bind.ServletRequestBindingException</exception-type>
    <location>/servletRequestBindingException.jsp</location>
</error-page>
<error-page>
    <error-code>405</error-code>
    <location>/methodNotSupported.jsp</location>
</error-page>

我宁愿使用弹簧异常处理。例如,我想根据传入的 Accept 标头创建动态响应,因此例如写出 json 或 xml 以获取休息异常。最好的办法是从此处理程序返回一个对象,该对象会自动转换为 json 或 xml,就像从处理程序返回的普通 dto 一样。

有没有办法捕捉这些较低级别的映射异常?

【问题讨论】:

    标签: spring-mvc exception-handling


    【解决方案1】:

    您不能使用@ExceptionHandler(因为正如您所说,这是用于处理从处理程序代码抛出的异常),但您仍然可以使用HandlerExceptionResolver framework 来执行此操作。

    默认情况下,DispatcherServlet 注册一个DefaultHandlerExceptionResolver 的实例:

    HandlerExceptionResolver 接口的默认实现,它解析标准 Spring 异常并将它们转换为相应的 HTTP 状态代码。

    HTTP 405 的生成实际上是在这个类中处理的,通过捕获处理程序映射代码抛出的HttpRequestMethodNotSupportedException

    因此,如果您想以不同的方式处理此异常,您可以提供自己的HandlerExceptionResolver 实现。继承DefaultHandlerExceptionResolver 并覆盖handleHttpRequestMethodNotSupported 方法可能是最简单的,从那里返回您的ModelAndView

    【讨论】:

      【解决方案2】:

      如果您包含自己的异常解析器,请小心包含默认异常解析器。如果您使用带注释的 @Exception 处理程序,则需要显式加载它们,否则它们将不再起作用。

      在这种情况下,FooBarHandlerExceptionResolver 扩展了 DefaultHandlerExceptionResolver 并提供了默认解析器未涵盖的方法。这让 FooBarHandlerExceptionResolver 可以处理我无法使用带注释的 @Exception 处理程序方法捕获的类级异常。

      <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver">
          <property name="order" value="1"/>
      </bean>
      <bean class="org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver" >
          <property name="order" value="2"/>
      </bean>
      <bean class="com.company.package.foo.FooBarHandlerExceptionResolver">
          <property name="order" value="3"/>
      </bean>
      

      这里是异常解析器

      public class FooBarHandlerExceptionResolver extends DefaultHandlerExceptionResolver {
          @Override
          protected ModelAndView doResolveException(HttpServletRequest request,
                  HttpServletResponse response,
                  Object handler,
                  Exception ex) {
              try {
                  if (ex instanceof UnsatisfiedServletRequestParameterException) {
                      return handleUnsatisfiedServletRequestParameter((UnsatisfiedServletRequestParameterException) ex, request, response,
                              handler);
                  }else {
                      super.doResolveException(request,response,handler,ex);
                  }
              }
              catch(Exception handlerException){
                  logger.warn("Handling of [" + ex.getClass().getName() + "] resulted in Exception", handlerException);
              }
              return null;
          }
      
          protected ModelAndView handleUnsatisfiedServletRequestParameter(UnsatisfiedServletRequestParameterException ex,
                  HttpServletRequest request,
                  HttpServletResponse response,
                  Object handler) throws Exception {
      
              logger.warn(ex.getMessage());
              return new ModelAndView("blank", new ModelMap("reason", ex.getMessage()));
      
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-13
        • 2014-05-23
        • 1970-01-01
        • 2010-12-24
        • 1970-01-01
        • 2011-12-26
        • 2013-08-13
        • 2014-05-11
        相关资源
        最近更新 更多