处理Spring中的ServletRequestBindingException等异常而不是Servlet容器

时间:2011-03-15 09:14:49

标签: spring-mvc exception-handling

我将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>

我宁愿使用spring异常处理。例如,我想基于传入的Accept头创建一个动态响应,因此要么写出json或xml作为休息例外。最好的方法是从这个处理程序返回一个自动转换为json或xml的对象,就像从处理程序返回的普通dto一样。

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

2 个答案:

答案 0 :(得分:6)

你不能使用@ExceptionHandler(因为正如你所说,这是为了处理处理程序代码中引发的异常),但你仍然可以使用HandlerExceptionResolver framework这样做。

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

  

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

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

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

答案 1 :(得分: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()));

    }
}