- 1.1,ExceptionHandler注解
- 1.2,ResponseStatusExceptionResolver
- 1.3,DefaultHandlerExceptionResolver
- 1.4,SimpleMappingExceptionResolver
SpringMVC的异常处理
-
在
@ExceptionHandler
方法的入参中可以加入Exception类型的参数,该参数即对应发生的异常对象 -
@ExceptionHandler
方法的入参不能传入Map,若希望把异常信息传到页面上,需要使用ModelAndView作为返回值 -
@ExceptionHandler
方法标记的异常有优先级的问题,NullPointerException
但是声明异常有RuntimeException
和Exception
此时会根据异常最继承关找到 继承深度最浅的这个RuntimeException
-
@ExceptionHandler
如果在当前Handler中找不到@ExceptionHandler
方法来处理当前方法出现的异常,则将去@ControllerAdvice
标记的类中查找@ExceptionHandler
标记的方法来处理异常 -
代码示例:
@RequestMapping("/testExceptionHandlerExceptionResolver")
public String testExceptionHandlerExceptionResolver(@RequestParam("i")int i){
System.out.println("result :" + (10 / i));
return "success";
}
- HandleException.java
@ControllerAdvice
public class HandleException {
@ExceptionHandler({RuntimeException.class})
public ModelAndView hanleRuntimeException(Exception ex){
System.out.println("出异常了:" + ex);
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception",ex);
return mv;
}
@ExceptionHandler({ArithmeticException.class})
public ModelAndView hanleArithmeticException(Exception ex){
System.out.println("出异常了:" + ex);
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception",ex);
return mv;
}
}
- error.jsp
${exception}
- index.jsp
<a href="${pageContext.request.contextPath}/testExceptionHandlerExceptionResolver?i=1">Test ExceptionHandlerExceptionResolver</a>
-
在异常及异常父类中使用
@ResponseStatus
注解 -
自定义异常
@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "用户名和密码不匹配!")
public class UserNameNotMatchPasswordException extends RuntimeException {
}
@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i")int i){
if(i == 2){
throw new UserNameNotMatchPasswordException();
}
System.out.println("======testResponseStatusExceptionResolver======");
return "success";
}
- 方法中带有
@ResponseStatus
注解 ,ResponseStatusExceptionResolver 解析到最后响应HttpStatus.UNAUTHORIZED
代码给客户,HttpStatus.UNAUTHORIZED
响应码401无权限。也可以响应其他的枚举。
@ResponseStatus(reason = "测试",value = HttpStatus.UNAUTHORIZED)
@RequestMapping("/testResponseStatusExceptionResolver")
public String testResponseStatusExceptionResolver(@RequestParam("i")int i){
if(i == 2){
throw new UserNameNotMatchPasswordException();
}
System.out.println("======testResponseStatusExceptionResolver======");
return "success";
}
-
对一些特殊的异常进行处理,比如:
NoSuchRequestHandlingMethodException
HttpRequestMethodNotSupportedException
HttpMediaTypeNotSupportedException
HttpMediaTypeNotAcceptableException -
示例代码:
@RequestMapping(value = "/testDefaultHandlerExceptionResolver",method = RequestMethod.POST)
public String testDefaultHandlerExceptionResolver(){
System.out.println("======testDefaultHandlerExceptionResolver======");
}
- 在DefaultHandlerExceptionResolver源码中进行了异常的处理
-
如果希望对所有异常进行统一处理可以使用 SimpleMappingExceptionResolver ,它将异常类名映射为
视图名,即发生异常时使用对应的视图报告异常 -
示例代码:
<!-- 配置SimpleMappingExceptionResolver来映射异常 -->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionAttribute" value="ex"></property><!-- 默认是exception-->
<property name="exceptionMappings">
<props>
<prop key="java.lang.ArrayIndexOutOfBoundsException">error</prop>
</props>
</property>
</bean>
@RequestMapping(value = "/testSimpleMappingExceptionResolver")
public String testSimpleMappingExceptionResolver(@RequestParam("i") int i){
String[] arr = new String[10];
System.out.println(arr[i]);
System.out.println("======testSimpleMappingExceptionResolver======");
return "success";
}
- error.jsp页面错误信息打印
${ex}
Spring MVC与Spring整合时实例被创建两次
- spring-mvc.xml配置:
<context:component-scan base-package="com.controller"/>
- spring.xml配置:
<context:component-scan base-package="com.controller"></context:component-scan>
-
问题产生的原因:
Spring MVC的配置文件和Spring的配置文件里面都使用了扫描注解
-
解决方法:
①,使 Spring 的 IOC 容器扫描的包和 SpringMVC 的 IOC 容器扫描的包没有重合的部分,把Handler和service/DAO放在不同的包下
②,使用 exclude-filter 和 include-filter 子节点来规定只能扫描的注解
-
Spring 的 IOC 容器和 SpringMVC 的 IOC 容器的关系:
-
SpringMVC 的 IOC 容器中的 bean 可以来引用 Spring IOC 容器中的 bean,反之不行,原因是:
-
Spring MVC是Spring的子类,子类可以引用父类,父类不能引用子类
-
从软件层面上来说,Spring MVC是展示层可以调用业务层,业务层不能调用展示层
-
-