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

发布于 2024-10-22 04:01:12 字数 760 浏览 0 评论 0原文

我正在将 springmvc 用于 REST 项目,每当客户端使用错误的 HTTP 方法调用 REST 资源时,就会抛出 servletrequestbindException。我无法在控制器中使用 @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 一样。

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

I am using springmvc for a REST project and whenever the client calls a rest resource with the wrong HTTP method, a servletrequestbindingexception is thrown. I cannot handle these exceptions with a @ExceptionHandler in the controller, as it happens not within the handler method but in the spring mapping layer.

Currently I declared a web.xml exception handling, this works:

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

I'd rather use spring exception handling though. For example I'd like to create a dynamic response based on teh incoming Accept header, so either writing out json or xml for a rest exception for example. The best would be to return an object from this handler that would automatically be converted to json or xml just like a normal dto returned from a handler.

Is there a way to catch these lower level mapping exceptions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

扛起拖把扫天下 2024-10-29 04:01:12

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

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

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

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

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

You can't use @ExceptionHandler (since as you say, this is for dealing exceptions thrown from within the handler code), but you can still use the HandlerExceptionResolver framework to do this.

By default, DispatcherServlet registers an instance of DefaultHandlerExceptionResolver:

Default implementation of the HandlerExceptionResolver interface that resolves standard Spring exceptions and translates them to corresponding HTTP status codes.

The generation of the HTTP 405 is actually handled in this class, by catching HttpRequestMethodNotSupportedException thrown by the handler-mapping code.

So if you want to handle this exception differently, you can provide your own implementation of HandlerExceptionResolver. It's probably easiest to subclass DefaultHandlerExceptionResolver and override the handleHttpRequestMethodNotSupported method, returning your ModelAndView from there.

北笙凉宸 2024-10-29 04:01:12

如果您包含自己的异常解析器,请小心包含默认的异常解析器。如果您使用带注释的 @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()));

    }
}

Be careful to include the default exception resolvers if you include your own. If you are using annotated @Exception handlers you need to explicitly load these or they will no longer function.

In this case, FooBarHandlerExceptionResolver extends DefaultHandlerExceptionResolver and provides a method that the default resolver doesn't cover. This lets FooBarHandlerExceptionResolver handle class-level exceptions that I couldn't catch with annotated @Exception handler methods.

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

Here is the exception resolver

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()));

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文