1、重要的接口和类
1.1 HandlerExceptionResolver
他是SpringMVC“九大组件”之一,SpringMVC异常处理核心接口。该接口定义了1个解析异常的方法:

1.2 ExceptionHandlerExceptionResolver
继承自AbstractHandlerMethodExceptionResolver
,该类主要处理Controller中用@ExceptionHandler注解定义的方法。该类是<annotation-driven/>
配置中定义的HandlerExceptionResolver实现类之一,大多数异常处理都是由该类操作。
- 在Controller中使用@ExceptionHandler处理异常
package com.xust.iot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletResponse;
@Controller
public class ExceptionHandlerTest {
@RequestMapping("/handler1")
public String handler1(Model model,@RequestParam(value = "value",required = false) int value){
int i=10/value;
model.addAttribute("msg","你好呀!");
model.addAttribute("msg1","10/"+value+"=");
model.addAttribute("res",i);
return "success";
}
/**
* 使用@ExceptionHandler注解可以告诉SpringMVC这是一个专门处理异常的方法
* 一个方法可处理多个异常,可以有多个处理异常的类
* @param e
* @return
*/
@ExceptionHandler(ArithmeticException.class)
public ModelAndView exceptionHandler1(Exception e, HttpServletResponse response){
System.out.println("在"+this.getClass().getName()+"中的异常处理方法");
ModelAndView mv=new ModelAndView("error");
mv.addObject("e",e);
mv.addObject("statusCode",response.getStatus());
return mv;
}
}
异常后的页面:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>出错啦</title>
</head>
<body>
<h3>出错啦!响应代码:${status},错误信息:${e}</h3>
</body>
</html>
测试结果:

像这样在Controller中借助@ExceptionHandler这个注解定义的异常处理方法只能在定义的那个Controller中使用,当Controller类十分多的时候,那么写异常处理方法就是个体力活了,因此SpringMVC就提供了@ControllerAdvice
这个注解,它只能用在类上,而这个类中的异常处理方法都是全局范围,如下定义一个类专门集中处理异常:
package com.xust.iot.handleException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletResponse;
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public ModelAndView handleArithmeticException(Exception e,HttpServletResponse response){
ModelAndView mv=new ModelAndView("error");
mv.addObject("status", response.getStatus());
mv.addObject("e",e);
return mv;
}
@ExceptionHandler(NullPointerException.class)
public ModelAndView handlerNulPointlException(Exception e,HttpServletResponse response){
ModelAndView mv=new ModelAndView("error");
mv.addObject("status", response.getStatus());
mv.addObject("e",e);
return mv;
}
@ExceptionHandler(Exception.class)
public ModelAndView handlerException(Exception e, HttpServletResponse response){
ModelAndView mv=new ModelAndView("error");
mv.addObject("status", response.getStatus());
mv.addObject("e",e);
return mv;
}
}
1.3 DefaultHandlerExceptionResovler
HandlerExceptionResolver接口的默认实现之一 ,基本上是Spring MVC内部使用,用来处理Spring定义的各种标准异常,将其转化为相对应的HTTP Status Code。其处理的异常类型有:
handleNoSuchRequestHandlingMethod
handleHttpRequestMethodNotSupported
handleHttpMediaTypeNotSupported
handleMissingServletRequestParameter
handleServletRequestBindingException
handleTypeMismatch
handleHttpMessageNotReadable
handleHttpMessageNotWritable
handleMethodArgumentNotValidException
handleMissingServletRequestParameter
handleMissingServletRequestPartException
handleBindException
1.4 ResponseStatusExceptionResovler
用来支持@ResponseStatus的使用,处理使用了ResponseStatus注解的异常,根据注解的内容,返回相应的HTTP Status Code和异常页面给客户端。如果Web应用程序中配置了ResponseStatusExceptionResolver,那么我们就可以使用ResponseStatus注解来注解我们自己编写的异常类,并在Controller中抛出该异常类,之后ResponseStatusExceptionResolver就会自动帮我们处理剩下的工作。<annotation-driven/>
配置中定义的HandlerExceptionResolver实现类之一。
自定义一个异常
package com.xust.iot.handleException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(reason = "用户不存在",value = HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
//......
}
另一个自定义异常
package com.xust.iot.handleException;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(reason = "输入的登录参数不合法",value = HttpStatus.BAD_REQUEST)
public class ParamterIllegalException extends RuntimeException {
}
在Controller中主动抛出这个异常看看效果:
package com.xust.iot.controller;
import com.xust.iot.beans.User;
import com.xust.iot.handleException.ParamterIllegalException;
import com.xust.iot.handleException.UserNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
@Controller
public class UserController {
@RequestMapping("/toLogin")
public String checkLogIn(@RequestParam(value ="username",defaultValue = "")String username,Model model) throws Throwable {
if("".equals(username)){
System.out.println("用户登录失败");
throw new ParamaterIllegalException();
}else if(!"admin".equals(username)){
System.out.println("用户登录失败");
throw new UserNotFoundException();
}
model.addAttribute("msg","欢迎你"+username+",现在是北京时间:"+new SimpleDateFormat("hh:mm:ss").format(new Date()));
System.out.println("用户登录成功");
return "success";
}
}
测试结果:

ExceptionHandlerExceptionResolver、DefaultHandlerExceptionResolver和ResponseStatusExceptionResolver这三个类是<mvc:annotation-driver>
配置后默认的3个实现类,他们的优先级是按书写的顺序由高到底。
1.5 SimpleMappingExceptionResovler
提供了将异常映射为视图的能力,高度可定制化。其提供的能力有: 1. 根据异常的类型,将异常映射到视图; 2. 可以为不符合处理条件没有被处理的异常,指定一个默认的错误返回; 3. 处理异常时,记录log信息; 4. 指定需要添加到Modle中的Exception属性,从而在视图中展示该属性。
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<!--在props标签中配置所有异常后对应的页面,其中:
key表示异常,应该写异常的全类名
<prop>标签体写该异常映射的视图名,只写视图名即可,SpringMVC的视图处理器会自动拼串
-->
<props>
<prop key="java.lang.NullPointerException" >error</prop>
</props>
</property>
</bean>