Spring 3 – 为NoSuchRequestHandlingMethodException创建ExceptionHandler

使用Spring 3,我喜欢使用ExceptionHandler注释创建一个exception处理程序,该注释将处理“找不到页面(404)”请求。 我使用以下代码来执行此操作。 但是当我指向一个不存在的URL时,将调用Spring定义的默认exception处理程序。

可能是我正在处理NoSuchRequestHandlingMethodExceptionexception。 如果是,那么我应该注册什么例外?

请你看看下面的代码,看看我做错了什么?

注意:如果我将@ExceptionHandler中的exception更改为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; } } 

当同一个类上的@RequestMapping方法抛出exception时,将调用@ExceptionHandler -annotated方法。 所以当你添加了抛出NullPointerException的映射时,这是有效的,因为映射的方法和exception处理程序在同一个类中。

如果没有找到映射,Spring无法将NoSuchRequestHandlingMethodException与您的@ExceptionHandler相关联,因为它没有将请求与处理程序方法匹配。 这在文档中没有明确提及,而是我观察到的行为。

如果你想特别处理这个exception,你将不得不使用更通用的HandlerExceptionResolver方法 ,而不是更专业的@ExceptionHandler技术。

在Spring 3.2中,您可以使用@ContollerAdvice为所有控制器创建一个ExceptionHandler,如下所示:

 @ControllerAdvice public class GeneralHandler { @ExceptionHandler public ModelAndView handleException (NoSuchRequestHandlingMethodException ex) { ModelAndView mav = new ModelAndView(); ... return mav; } } 

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

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

你可以采用这种方法,它是好主意和工作,只需要使用特定的Handler抛出exception的必要性使@ExceptionHandler看起来不那么有用。