(我在Spring 3.1中找到了实现它的方法,此答案的第二部分对此进行了描述)
请参见第16.11章处理 Spring
Reference的异常
- 您可以实现HandlerExceptionResolver( 使用servlet而不是portlet包 )-这是某种全局@ExceptionHandler
- 如果您没有针对异常的特定逻辑,而只是特定视图,则可以使用SimpleMappingExceptionResolver,它至少是的实现
HandlerExceptionResolver
,您可以在其中指定异常名称模式和视图(jsp),当引发异常。例如:
<bean p:defaultErrorView="uncaughtException"> <property name="exceptionMappings"><props> <prop key=".DataAccessException">dataAccessFailure</prop> <prop key=".TypeMismatchException">resourceNotFound</prop> <prop key=".AccessDeniedException">accessDenied</prop> </props> </property> </bean>
在 Spring 3.2+中,
可以使用注释类
@ControllerAdvice,该类中的所有
@ExceptionHandler方法都以全局方式工作。
在 Spring 3.1 中没有
@ControllerAdvice。但是只要稍加修改,就可以具有类似的功能。
关键是对工作方式的理解
@ExceptionHandler。在Spring
3.1中有一个类
ExceptionHandlerExceptionResolver。此类(在其超类的帮助下)实现接口
HandlerExceptionResolver并负责调用
@ExceptionHandler方法。
该
HandlerExceptionResolver接口只有一种方法:
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);`.
当请求由Spring3.x控制器方法处理时,该方法(由表示
org.springframework.web.method.HandlerMethod)就是
handler参数。
的
ExceptionHandlerExceptionResolver用途
handler(
HandlerMethod),以获得控制器类和扫描它用于与所注解的方法
@ExceptionHandler。如果其中一个方法与例外(
ex)相符,则会调用此方法以处理该例外。(否则
null返回此信号是为了表示此异常解析器不承担任何责任)。
第一个想法是实现一个
HandlerExceptionResolver行为类似于的自己
ExceptionHandlerExceptionResolver,但
@ExceptionHandler与其在控制器类中进行搜索,不如在控制器类中进行搜索。缺点是,
ExceptionHandlerExceptionResolver必须手动配置(复制(或子类),并且必须)所有不错的消息转换器,参数解析器和返回值处理程序(真正的配置,并且仅
ExceptionHandlerExceptionResolver由spring自动完成)。所以我想到了另一个想法:
实现一个简单的
HandlerExceptionResolver“将”异常“转发”到THE(已配置)
ExceptionHandlerExceptionResolver,但将其修改后
handler指向包含全局Exception处理程序的Bean(我称它们为Global,因为它们对所有控制器都起作用)。
这是实现:
GlobalMethodHandlerExeptionResolver
import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.Ordered; import org.springframework.util.StringUtils; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; public class GlobalMethodHandlerExeptionResolver implements HandlerExceptionResolver, Ordered { @Override public int getOrder() { return -1; // } private ExceptionHandlerExceptionResolver realExceptionResolver; private List<GlobalMethodExceptionResolverContainer> containers; @Autowired public GlobalMethodHandlerExeptionResolver( ExceptionHandlerExceptionResolver realExceptionResolver, List<GlobalMethodExceptionResolverContainer> containers) { this.realExceptionResolver = realExceptionResolver; this.containers = containers; } @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { for (GlobalMethodExceptionResolverContainer container : this.containers) { ModelAndView result = this.realExceptionResolver.resolveException( request, response, handlerMethodPointingGlobalExceptionContainerBean(container), ex); if (result != null) return result; } // we feel not responsible return null; } protected HandlerMethod handlerMethodPointingGlobalExceptionContainerBean( GlobalMethodExceptionResolverContainer container) { try { return new HandlerMethod(container, GlobalMethodExceptionResolverContainer.class. getMethod("fakeHanderMethod")); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException(e); } } }全局处理程序必须实现此接口(以便找到并实现
fakeHanderMethod用于
handler
public interface GlobalMethodExceptionResolverContainer { void fakeHanderMethod(); }全局处理程序的示例:
@Component public class JsonGlobalExceptionResolver implements GlobalMethodExceptionResolverContainer { @Override public void fakeHanderMethod() { } @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody public ValidationErrorDto handleMethodArgumentNotValidException( MethodArgumentNotValidException validationException, Locale locale) { ... return validationErrorDto; } }顺便说一句:您不需要注册,
GlobalMethodHandlerExeptionResolver因为spring会自动注册所有
HandlerExceptionResolver为异常解析器实现的bean
。如此简单
<bean />就足够了。



