Spring 3 - 为 NoSuchRequestHandlingMethodException 创建 ExceptionHandler

28

使用Spring 3,我想使用ExceptionHandler注释创建一个异常处理程序来处理"找不到页面 (404)"请求。我正在使用以下代码进行操作。但是,当我指向不存在的URL时,Spring定义的默认异常处理程序被调用。

可能是因为我正在处理NoSuchRequestHandlingMethodException异常。如果是这样,那么我应该注册哪个异常?

你能否请查看以下代码并看看我错在哪里了?

注意:如果我将@ExceptionHandler中的异常更改为NullPointerException,然后创建一个RequestMapping来抛出空指针,那将起作用。

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RequestMapping;

    import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;

    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.web.servlet.ModelAndView;

    @Controller
    public class GeneralHandler {
      private final Log logger = LogFactory.getLog(getClass());

      @ExceptionHandler(NoSuchRequestHandlingMethodException.class)
      public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
        ModelAndView mav = new ModelAndView();
        logger.error("Exception found: " + ex);
        return mav;
      }
    }
3个回答

41

@ExceptionHandler注解的方法在同一类上的@RequestMapping方法抛出异常时被调用。因此,当您添加了抛出NullPointerException的映射时,这起作用了,因为映射方法和异常处理程序在同一个类中。

当没有找到映射时,Spring无法将NoSuchRequestHandlingMethodException与您的@ExceptionHandler关联,因为它还没有匹配请求到处理程序方法。尽管文档中没有明确提到,但这是我观察到的行为。

如果您要特殊处理此异常,您需要使用更通用的HandlerExceptionResolver方法而不是更专业的@ExceptionHandler技术。


2
谢谢。我会使用HandlerExceptionResolver方法。 - sgsweb

16

在Spring 3.2中,您可以使用@ContollerAdvice来为所有控制器设置异常处理程序,像这样:

@ControllerAdvice
public class GeneralHandler {

   @ExceptionHandler
   public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) {
        ModelAndView mav = new ModelAndView();
        ...
        return mav;
   }
}
你甚至可以添加更多的注释来返回序列化的JSON。

你甚至可以添加更多的注释来返回序列化的JSON

@ExceptionHandler
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public RestError resolveBindingException ( MethodArgumentNotValidException methodArgumentNotValidException, Locale locale )
    {
        BindingResult bindingResult = methodArgumentNotValidException.getBindingResult();
        return getRestError(bindingResult, locale);
    }

这基本上就是我最终所做的,但由于我还使用了ContentNegotiatingViewResolver,因此我最终捕获了“Exception”,然后将其包装在一个带有JSON和XML序列化注释的类中,并返回该类而不是ModelAndView,因此客户端最终会获取包装对象的序列化版本。 - Mick Sear

2
你可以采用这种方法,它是个好主意并且行得通。只有在特定的处理程序内部抛出异常才需要使用@ExceptionHandler,因此它看起来并不是那么有用。请注意保留HTML标签。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接