我将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一样。
有没有办法捕获这些较低级别的映射异常?
答案 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()));
}
}