苹果如何解除sim卡锁定定怎么解除

Spring MVC中异常处理的类体系结构
下图中,我画出了Spring MVC中,跟异常处理相关的主要类和接口。
在Spring MVC中,所有用于处理在请求映射和请求处理过程中抛出的异常的类,都要实现HandlerExceptionResolver接口。AbstractHandlerExceptionResolver实现该接口和Orderd接口,是HandlerExceptionResolver类的实现的基类。ResponseStatusExceptionResolver等具体的异常处理类均在AbstractHandlerExceptionResolver之上,实现了具体的异常处理方式。一个基于Spring MVC的Web应用程序中,可以存在多个实现了HandlerExceptionResolver的异常处理类,他们的执行顺序,由其order属性决定, order值越小,越是优先执行, 在执行到第一个返回不是null的ModelAndView的Resolver时,不再执行后续的尚未执行的Resolver的异常处理方法。。
下面我逐个介绍一下SpringMVC提供的这些异常处理类的功能。
DefaultHandlerExceptionResolver
HandlerExceptionResolver接口的默认实现,基本上是Spring MVC内部使用,用来处理Spring定义的各种标准异常,将其转化为相对应的HTTP Status Code。其处理的异常类型有:
handleNoSuchRequestHandlingMethod
handleHttpRequestMethodNotSupported
handleHttpMediaTypeNotSupported
handleMissingServletRequestParameter
handleServletRequestBindingException
handleTypeMismatch
handleHttpMessageNotReadable
handleHttpMessageNotWritable
handleMethodArgumentNotValidException
handleMissingServletRequestParameter
handleMissingServletRequestPartException
handleBindException
ResponseStatusExceptionResolver
用来支持ResponseStatus的使用,处理使用了ResponseStatus注解的异常,根据注解的内容,返回相应的HTTP Status Code和内容给客户端。如果Web应用程序中配置了ResponseStatusExceptionResolver,那么我们就可以使用ResponseStatus注解来注解我们自己编写的异常类,并在Controller中抛出该异常类,之后ResponseStatusExceptionResolver就会自动帮我们处理剩下的工作。
这是一个自己编写的异常,用来表示订单不存在:
@ResponseStatus(value=HttpStatus.NOT_FOUND, reason=&No such Order&)
public class OrderNotFoundException extends RuntimeException {
这是一个使用该异常的Controller方法:
@RequestMapping(value=&/orders/{id}&, method=GET)
public String showOrder(@PathVariable(&id&) long id, Model model) {
Order order = orderRepository.findOrderById(id);
if (order == null) throw new OrderNotFoundException(id);
model.addAttribute(order);
return &orderDetail&;
这样,当OrderNotFoundException被抛出时,ResponseStatusExceptionResolver会返回给客户端一个HTTP Status Code为404的响应。
AnnotationMethodHandlerExceptionResolver和ExceptionHandlerExceptionResolver
用来支持ExceptionHandler注解,使用被ExceptionHandler注解所标记的方法来处理异常。其中AnnotationMethodHandlerExceptionResolver在3.0版本中开始提供,ExceptionHandlerExceptionResolver在3.1版本中开始提供,从3.2版本开始,Spring推荐使用ExceptionHandlerExceptionResolver。
如果配置了AnnotationMethodHandlerExceptionResolver和ExceptionHandlerExceptionResolver这两个异常处理bean之一,那么我们就可以使用ExceptionHandler注解来处理异常。
下面是几个ExceptionHandler注解的使用例子:
@Controller
public class ExceptionHandlingController {
// @RequestHandler methods
// 以下是异常处理方法
// 将DataIntegrityViolationException转化为Http Status Code为409的响应
@ResponseStatus(value=HttpStatus.CONFLICT, reason=&Data integrity violation&)
@ExceptionHandler(DataIntegrityViolationException.class)
public void conflict() {
// Nothing to do
// 针对SQLException和DataAccessException返回视图databaseError
@ExceptionHandler({SQLException.class,DataAccessException.class})
public String databaseError() {
// Nothing to do.
Returns the logical view name of an error page, passed to
// the view-resolver(s) in usual way.
// Note that the exception is _not_ available to this view (it is not added to
// the model) but see &Extending ExceptionHandlerExceptionResolver& below.
return &databaseError&;
// 创建ModleAndView,将异常和请求的信息放入到Model中,指定视图名字,并返回该ModleAndView
@ExceptionHandler(Exception.class)
public ModelAndView handleError(HttpServletRequest req, Exception exception) {
logger.error(&Request: & + req.getRequestURL() + & raised & + exception);
ModelAndView mav = new ModelAndView();
mav.addObject(&exception&, exception);
mav.addObject(&url&, req.getRequestURL());
mav.setViewName(&error&);
需要注意的是,上面例子中的ExceptionHandler方法的作用域,只是在本Controller类中。如果需要使用ExceptionHandler来处理全局的Exception,则需要使用ControllerAdvice注解。
@ControllerAdvice
class GlobalDefaultExceptionHandler {
public static final String DEFAULT_ERROR_VIEW = &error&;
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
// 如果异常使用了ResponseStatus注解,那么重新抛出该异常,Spring框架会处理该异常。
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
// 否则创建ModleAndView,处理该异常。
ModelAndView mav = new ModelAndView();
mav.addObject(&exception&, e);
mav.addObject(&url&, req.getRequestURL());
mav.setViewName(DEFAULT_ERROR_VIEW);
SimpleMappingExceptionResolver
提供了将异常映射为视图的能力,高度可定制化。其提供的能力有:
根据异常的类型,将异常映射到视图;
可以为不符合处理条件没有被处理的异常,指定一个默认的错误返回;
处理异常时,记录log信息;
指定需要添加到Modle中的Exception属性,从而在视图中展示该属性。
@Configuration
@EnableWebMvc
public class MvcConfiguration extends WebMvcConfigurerAdapter {
@Bean(name=&simpleMappingExceptionResolver&)
public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
Properties mappings = new Properties();
mappings.setProperty(&DatabaseException&, &databaseError&);
mappings.setProperty(&InvalidCreditCardException&, &creditCardError&);
r.setExceptionMappings(mappings);
// 默认为空
r.setDefaultErrorView(&error&);
// 默认没有
r.setExceptionAttribute(&ex&);
r.setWarnLogCategory(&example.MvcLogger&);
自定义ExceptionResolver
Spring MVC的异常处理非常的灵活,如果提供的ExceptionResolver类不能满足使用,我们可以实现自己的异常处理类。可以通过继承SimpleMappingExceptionResolver来定制Mapping的方式和能力,也可以直接继承AbstractHandlerExceptionResolver来实现其它类型的异常处理类。
Spring MVC是如何创建和使用这些Resolver的?
首先看Spring MVC是怎么加载异常处理bean的。
Spring MVC有两种加载异常处理类的方式,一种是根据类型,这种情况下,会加载ApplicationContext下所有实现了ExceptionResolver接口的bean,并根据其order属性排序,依次调用;一种是根据名字,这种情况下会加载ApplicationContext下,名字为handlerExceptionResolver的bean。
不管使用那种加载方式,如果在ApplicationContext中没有找到异常处理bean,那么Spring MVC会加载默认的异常处理bean。
默认的异常处理bean定义在DispatcherServlet.properties中。
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
以下代码摘自ispatcherServlet,描述了异常处理类的加载过程:
* Initialize the HandlerMappings used by this class.
* &p&If no HandlerMapping beans are defined in the BeanFactory for this namespace,
* we default to BeanNameUrlHandlerMapping.
private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;
if (this.detectAllHandlerMappings) {
// Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
Map&String, HandlerMapping& matchingBeans =
BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
if (!matchingBeans.isEmpty()) {
this.handlerMappings = new ArrayList&HandlerMapping&(matchingBeans.values());
// We keep HandlerMappings in sorted order.
OrderComparator.sort(this.handlerMappings);
HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
this.handlerMappings = Collections.singletonList(hm);
catch (NoSuchBeanDefinitionException ex) {
// Ignore, we'll add a default HandlerMapping later.
// Ensure we have at least one HandlerMapping, by registering
// a default HandlerMapping if no other mappings are found.
if (this.handlerMappings == null) {
this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
if (logger.isDebugEnabled()) {
logger.debug(&No HandlerMappings found in servlet '& + getServletName() + &': using default&);
然后看Spring MVC是怎么使用异常处理bean的。
Spring MVC把请求映射和处理过程放到try catch中,捕获到异常后,使用异常处理bean进行处理。
所有异常处理bean按照order属性排序,在处理过程中,遇到第一个成功处理异常的异常处理bean之后,不再调用后续的异常处理bean。
以下代码摘自DispatcherServlet,描述了处理异常的过程。
* Process the actual dispatching to the handler.
* &p&The handler will be obtained by applying the servlet's HandlerMappings in order.
* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
* to find the first that supports the handler class.
* &p&All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
* themselves to decide which methods are acceptable.
* @param request current HTTP request
* @param response current HTTP response
* @throws Exception in case of any kind of processing failure
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest =
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
ModelAndView mv = null;
Exception dispatchException = null;
processedRequest = checkMultipart(request);
multipartRequestParsed = (processedRequest != request);
// Determine handler for the current request.
mappedHandler = getHandler(processedRequest);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
// Determine handler adapter for the current request.
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// Process last-modified header, if supported by the handler.
String method = request.getMethod();
boolean isGet = &GET&.equals(method);
if (isGet || &HEAD&.equals(method)) {
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug(&Last-Modified value for [& + getRequestUri(request) + &] is: & + lastModified);
if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
// Actually invoke the handler.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
applyDefaultViewName(request, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
catch (Exception ex) {
dispatchException =
processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
catch (Exception ex) {
triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
catch (Error err) {
triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
if (asyncManager.isConcurrentHandlingStarted()) {
// Instead of postHandle and afterCompletion
if (mappedHandler != null) {
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
// Clean up any resources used by a multipart request.
if (multipartRequestParsed) {
cleanupMultipart(processedRequest);
* Determine an error ModelAndView via the registered HandlerExceptionResolvers.
* @param request current HTTP request
* @param response current HTTP response
* @param handler the executed handler, or {@code null} if none chosen at the time of the exception
* (for example, if multipart resolution failed)
* @param ex the exception that got thrown during handler execution
* @return a corresponding ModelAndView to forward to
* @throws Exception if no error ModelAndView found
protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception {
// Check registered HandlerExceptionResolvers...
ModelAndView exMv = null;
for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
if (exMv != null) {
if (exMv != null) {
if (exMv.isEmpty()) {
request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
return null;
// We might still need view name translation for a plain error model...
if (!exMv.hasView()) {
exMv.setViewName(getDefaultViewName(request));
if (logger.isDebugEnabled()) {
logger.debug(&Handler execution resulted in exception - forwarding to resolved error view: & + exMv, ex);
WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
return exMv;
何时该使用何种ExceptionResolver?
Spring提供了很多选择和非常灵活的使用方式,下面是一些使用建议:
如果自定义异常类,考虑加上ResponseStatus注解;
对于没有ResponseStatus注解的异常,可以通过使用ExceptionHandler+ControllerAdvice注解,或者通过配置SimpleMappingExceptionResolver,来为整个Web应用提供统一的异常处理。
如果应用中有些异常处理方式,只针对特定的Controller使用,那么在这个Controller中使用ExceptionHandler注解。
不要使用过多的异常处理方式,不然的话,维护起来会很苦恼,因为异常的处理分散在很多不同的地方。
阅读(...) 评论()SpringMVC异常处理机制详解[附带源码分析] - format丶 - 推酷
SpringMVC异常处理机制详解[附带源码分析] - format丶
SpringMVC是目前主流的Web MVC框架之一。
如果有同学对它不熟悉,那么请参考它的入门blog:
本文将分析SpringMVC的异常处理内容,让读者了解SpringMVC异常处理的设计原理。
重要接口和类介绍
1.&HandlerExceptionResolver接口
SpringMVC异常处理核心接口。该接口定义了1个解析异常的方法:
ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws E
2.&AbstractHandlerExceptionResolver抽象类
实现了HandlerExceptionResolver和Ordered接口的抽象类。
先看下属性:
再看下接口的实现:
3.&AbstractHandlerMethodExceptionResolver抽象类
继承AbstractHandlerExceptionResolver抽象类的抽象类。 该类主要就是为HandlerMethod类服务,既handler参数是HandlerMethod类型。
该类重写了shouldApplyTo方法:
doResolveException抽象方法的实现中调用了doResolveHandlerMethodException方法,该方法也是1个抽象方法。
4.&ExceptionHandlerExceptionResolver类
继承自AbstractHandlerMethodExceptionResolver,
该类主要处理Controller中用@ExceptionHandler注解定义的方法。
该类也是&annotation-driven/&配置中定义的HandlerExceptionResolver实现类之一,大多数异常处理都是由该类操作。
该类比较重要,我们来详细讲解一下。
首先我们看下这个类的属性:
再来看下该类的doResolveHandlerMethodException抽象方法的实现:
默认的HandlerMethodArgumentResolver集合:
默认的HandlerMethodReturnValueHandler集合:
其中关于HandlerMethodArgumentResolver、HandlerMethodReturnValueHandler接口,HandlerMethodArgumentResolverComposite、HandlerMethodReturnValueHandlerComposite类,HandlerMethod、ServletInvocableHandlerMethod类等相关知识的请参考楼主的其他博客:
我们进入getExceptionHandlerMethod方法看看是如何得到ServletInvocableHandlerMethod的:
我们看到getExceptionHandlerMethod中会实例化ExceptionHandlerMethodResolver,我们看看这个类到底是什么东西?
ExceptionHandlerMethodResolver是一个会在Class及Class的父类集合中找出带有@ExceptionHandler注解的类,该类带有key为Throwable,value为Method的缓存属性。
ExceptionHandlerMethodResolver的构造过程:
ExceptionHandlerExceptionResolver处理过程总结一下:根据用户调用Controller中相应的方法得到HandlerMethod,之后构造ExceptionHandlerMethodResolver,构造ExceptionHandlerMethodResolver有2种选择,1.通过HandlerMethod拿到Controller,找出Controller中带有@ExceptionHandler注解的方法(局部) 2.找到@ControllerAdvice注解配置的类中的@ExceptionHandler注解的方法(全局)。这2种方式构造的ExceptionHandlerMethodResolver中都有1个key为Throwable,value为Method的缓存。之后通过发生的异常找出对应的Method,然后调用这个方法进行处理。这里异常还有个优先级的问题,比如发生的是NullPointerException,但是声明的异常有
Throwable和Exception,这时候 ExceptionHandlerMethodResolver找Method的时候会根据异常的最近继承关系找到继承深度最浅的那个异常,即Exception。
5.&DefaultHandlerExceptionResolver类
继承自AbstractHandlerExceptionResolver抽象类。
&annotation-driven/&配置中定义的HandlerExceptionResolver实现类之一。
该类的doResolveException方法中主要对一些特殊的异常进行处理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
6.&ResponseStatusExceptionResolver类
继承自AbstractHandlerExceptionResolver抽象类。
&annotation-driven/&配置中定义的HandlerExceptionResolver实现类之一。
该类的doResolveException方法主要在异常及异常父类中找到@ResponseStatus注解,然后使用这个注解的属性进行处理。
-------------------------------------------------------------------------------------------------------------------------------------------------
说明一下为什么ExceptionHandlerExceptionResolver、DefaultHandlerExceptionResolver、ResponseStatusExceptionResolver是&annotation-driven/&配置中定义的HandlerExceptionResolver实现类。
我们看下&annotation-driven/&配置解析类AnnotationDrivenBeanDefinitionParser中部分代码片段:
这3个ExceptionResolver最终被会加入到DispatcherServlet中的handlerExceptionResolvers集合中。
其中ExceptionHandlerExceptionResolver优先级最高,ResponseStatusExceptionResolver第二,DefaultHandlerExceptionResolver第三。
为什么ExceptionHandlerExceptionResolver优先级最高,因为order属性值最低,这部分的知识请参考:
-------------------------------------------------------------------------------------------------------------------------------------------------
7.&@ResponseStatus注解
让1个方法或异常有状态码(status)和理由(reason)返回。这个状态码是http响应的状态码。
8.&SimpleMappingExceptionResolver类
继承自AbstractHandlerExceptionResolver抽象类,是1个根据配置进行解析异常的类,包括配置异常类型,默认的错误视图,默认的响应码,异常映射等配置属性。 本文不分析,有兴趣的读者可自行查看源码。
下面我们来分析SpringMVC处理异常的源码。
SpringMVC在处理请求的时候,通过RequestMappingHandlerMapping得到HandlerExecutionChain,然后通过RequestMappingHandlerAdapter得到1个ModelAndView对象,这在之前发生的异常都会被catch到,然后得到这个异常并作为参数传入到processDispatchResult方法处理。
processDispatchResult方法如下:
processHandlerException方法:
接下里讲常用ExceptionResolver的实例。
1. ExceptionHandlerExceptionResolver
@Controller
@RequestMapping(value = &/error&)
public class TestErrorController {
@RequestMapping(&/exception&)
public ModelAndView exception(ModelAndView view) throws ClassNotFoundException {
view.setViewName(&index&);
throw new ClassNotFoundException(&class not found&);
@RequestMapping(&/nullpointer&)
public ModelAndView nullpointer(ModelAndView view) {
view.setViewName(&index&);
String str =
str.length();
@ExceptionHandler(RuntimeException.class)
public ModelAndView error(RuntimeException error, HttpServletRequest request) {
ModelAndView mav = new ModelAndView();
mav.setViewName(&error&);
mav.addObject(&param&, &Runtime error&);
@ExceptionHandler()
public ModelAndView error(Exception error, HttpServletRequest request, HttpServletResponse response) {
ModelAndView mav = new ModelAndView();
mav.setViewName(&error&);
mav.addObject(&param&, &Exception error&);
@ExceptionHandler(NullPointerException.class)
public ModelAndView error(ModelAndView mav) {
mav.setViewName(&error&);    mav.addObject(&param&, &NullPointer error&);
分析一下:
如果用户进入nullpointer方法,str对象还未初始化,会发生NullPointerException。如果去掉最后1个注释掉的error方法,那么会报错。因为ExceptionHandlerExceptionResolver的默认HandlerMethodArgumentResolver中只有ServletRequestMethodArgumentResolver和ServletResponseMethodArgumentResolver(所以其他2个error方法中的request和response参数没问题)。 所以我们给最后1个error方法加了注释。
由于TestErrorController控制器中有2个带有@ExceptionHandler注解的方法,之前分析的ExceptionHandlerMethodResolver构造过程中,会构造ExceptionHandlerMethodResolver,ExceptionHandlerMethodResolver内部会有1个key分别为RuntimeException和Exception,value分别为第一个和第二个error方法的缓存。由于NullPointerException的继承关系离RuntimeException比Exception近,因此最终进入了第一个error方法。
如果用户进入exception方法,同理。ClassNotFoundException继承自Exception,跟RuntimeException没关系,那么进入第二个error方法。
说明一下,两个error方法返回值都是ModelAndView,这是因为ExceptionHandlerMethodResolver的默认HandlerMethodReturnValueHandler中有ModelAndViewMethodReturnValueHandler。还有其他的比如ModelMethodProcessor、ViewMethodReturnValueHandler和ViewNameMethodReturnValueHandler等。这3个分别代表返回值Model,View和字符串。 有兴趣的读者可自行查看源码。
上个例子是基于Controller的@ExceptionHandler注解方法,每个Controller都需要写@ExceptionHandler注解方法(写个BaseController可不用每个Controller都写单独的@ExceptionHandler注解方法)。
ExceptionHandlerMethodResolver内部找不到Controller的@ExceptionHandler注解的话,会找@ControllerAdvice中的@ExceptionHandler注解方法。
因此,我们也可以写1个ControllerAdvice。
@ControllerAdvice
public class ExceptionControllerAdvice {
@ExceptionHandler(Throwable.class)
@ResponseBody
public Map&String, Object& ajaxError(Throwable error, HttpServletRequest request, HttpServletResponse response) {
Map&String, Object& map = new HashMap&String, Object&();
map.put(&error&, error.getMessage());
map.put(&result&, &error&);
此类中的error方法代表着全局异常处理方法。
该方法可对ajax操作进行异常处理,我们返回值使用了@ResponseBody进行了处理,然后配置json消息转换器即可,这样该方法响应给客户端的数据就变成了json数据。 这方面的知识请参考:
2.&ResponseStatusExceptionResolver
先定义1个自定义异常:
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public class UnauthorizedException extends RuntimeException {
Controller代码:
@Controller
@RequestMapping(value = &/error&)
public class TestErrorController {
@RequestMapping(&/unauth&)
public ModelAndView unauth(ModelAndView view) {
view.setViewName(&index&);
throw new UnauthorizedException();
由于该类没有写@ExceptionHandler注解,因此ExceptionHandlerExceptionResolver不能解析unauth触发的异常。接下来由ResponseStatusExceptionResolver进行解析,由于触发的异常UnauthorizedException带有@ResponseStatus注解。因此会被ResponseStatusExceptionResolver解析到。最后响应HttpStatus.UNAUTHORIZED代码给客户端。HttpStatus.UNAUTHORIZED代表响应码401,无权限。 关于其他的响应码请参考HttpStatus枚举类型源码。
3.&DefaultHandlerExceptionResolver
直接上代码:
@Controller
@RequestMapping(value = &/error&)
public class TestErrorController {
@RequestMapping(&/noHandleMethod&)
public ModelAndView noHandleMethod(ModelAndView view, HttpServletRequest request) throws NoSuchRequestHandlingMethodException {
view.setViewName(&index&);
throw new NoSuchRequestHandlingMethodException(request);
用户进入noHandleMethod方法触发NoSuchRequestHandlingMethodException异常,由于没配置@ExceptionHandler以及该异常没有@ResponseStatus注解,最终由DefaultHandlerExceptionResolver解析,由于NoSuchRequestHandlingMethodException属于DefaultHandlerExceptionResolver解析的异常,因此被DefaultHandlerExceptionResolver解析。NoSuchRequestHandlingMethodException会发生404错误。
关于DefaultHandlerExceptionResolver可以处理的其他异常,请参考DefaultHandlerExceptionResolver源码。
扩展ExceptionHandlerExceptionResolver功能
SpringMVC提供的HandlerExceptionResolver基本上都能满足我们的开发要求,因此本文就不准备写自定义的HandlerExceptionResolver。
既然不写自定义的HandlerExceptionResolver,我们就来扩展ExceptionHandlerExceptionResolver来吧,让它支持更多的功能。
比如为ExceptionHandlerExceptionResolver添加更多的HandlerMethodArgumentResolver,ExceptionHandlerExceptionResolver默认只能有2个HandlerMethodArgumentResolver和ServletRequestMethodArgumentResolver(处理ServletRequest、WebRequest、MultipartRequest、HttpSession等参数)和ServletResponseMethodArgumentResolver(处理ServletResponse、OutputStream或Writer参数)。
ModelAndView这种类型的参数会被ServletModelAttributeMethodProcessor处理。因此我们需要给ExceptionHandlerExceptionResolver添加ServletModelAttributeMethodProcessor这个HandlerMethodArgumentResolver。由于ServletModelAttributeMethodProcessor处理ModelAndView参数会使用WebDataBinderFactory参数,因此我们得重写doResolveHandlerMethodException方法,所以新写了1个类继承ExceptionHandlerExceptionResolver。
public class MyExceptionHandlerExceptionResolver extends ExceptionHandlerExceptionResolver{
public MyExceptionHandlerExceptionResolver() {
List&HandlerMethodArgumentResolver& list = new ArrayList&HandlerMethodArgumentResolver&();
list.add(new ServletModelAttributeMethodProcessor(true));
this.setCustomArgumentResolvers(list);
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {
ServletInvocableHandlerMethod exceptionHandlerMethod = getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
exceptionHandlerMethod.setDataBinderFactory(new ServletRequestDataBinderFactory(null, null));
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(getArgumentResolvers());
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(getReturnValueHandlers());
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
if (logger.isDebugEnabled()) {
logger.debug(&Invoking @ExceptionHandler method: & + exceptionHandlerMethod);
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, exception);
catch (Exception invocationEx) {
logger.error(&Failed to invoke @ExceptionHandler method: & + exceptionHandlerMethod, invocationEx);
return null;
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
mav.setViewName(mavContainer.getViewName());
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
class=&org.format.demo.support.exceptionResolver.MyExceptionHandlerExceptionResolver&&
name=&order& value=&-1&/&
配置完成之后,然后去掉本文实例讲解中ExceptionHandlerExceptionResolver的代码,并去掉支持NullPointerException异常的那个方法的注释。
测试如下:
读者可根据需求自己实现其他的扩展功能。 或者实现HandlerExceptionResolver接口新写1个HandlerExceptionResolver实现类。
新的的HandlerExceptionResolver实现类只需在配置文件中定义即可,然后配置优先级。DispatcherServlet初始化HandlerExceptionResolver的时候会自动寻找容器中实现了HandlerExceptionResolver接口的类,然后添加进来。
分析了SpringMVC的异常处理机制并介绍了几个重要的接口和类,并分析了在&annotation-driven/&中定义的3个常用的HandlerExceptionResolver。
之后又编写了1个继承自ExceptionHandlerExceptionResolver类的异常解析类,巩固了之前分析的知识。
希望这篇文章能帮助读者了解SpringMVC异常机制。
文中难免有错误,希望读者能够指明出来。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致

我要回帖

更多关于 sim卡已锁定怎么解锁 的文章

 

随机推荐