文章目录
- 一、Handler ExceptionResolver处理异常
- 二、@ExceptionHandler注解
- 三、重点:添加@ExceptionHandler注解方法的形参只能是异常类型
- 四、重点2:捕获所有方法的异常—@ControllerAdvice注解
- 五、总结
- 六、ResponseStatusExceptionResolve自定义异常显示页面
- 七、扩展@ResponseStatus 用法
- 八、其他异常处理
- 8.1 DefaultHandlerExceptionResolver
- 8.2 SymbolMappingExceptionResolver
一、Handler ExceptionResolver处理异常
Spring mvc处理异常的是顶级接口Handler ExceptionResolver
看一下该接口的源码所在的包
可以看到HandlerExceptionResolver接口在spring-webmvc包下
来看一下这个接口的实现类
上面每一个实现类都对应一种异常的处理方式
,重点来看ExceptionHandlerExceptionResolver
二、@ExceptionHandler注解
ExceptionHandlerExceptionResolver主要提供了
@ExceptionHandler 注解
通过在方法上添加该注解来实现异常处理
在Controller层写个异常
如图所示,这行代码会报ArithmeticException算术异常,以前我们可以使用try catch来处理,现在把try catch注释掉,再写一个方法HandlerArithmeticException(),并使用注解的形式来捕获异常,如下
添加@ExceptionHandler注解的这个方法就可以捕获本类中的异常,想要捕获指定的异常,就在注解后面添加参数,
上面我添加的是算数异常ArithmeticException.class因此,当前的这个方法就可以捕获上面的算术异常。代码如下
public String testExceptionHandler(){
//try {
System.out.println( 1/0 );
//}catch(ArithmeticException e) e
return "success";
}
//该方法可以捕获本类中抛出的ArithmeticException异常
@ExceptionHandler({ArithmeticException.class})
public String handlerArithmeticException(ArithmeticException e){
System.out.println(e);
return "error";
}
下面再写一个数组越界异常:
ArrayIndexOutOfBoundsException
用同一个方法捕获,只要在@HandlerException注解后面追加要捕获的异常的类名就可以
public String testExceptionHandler2(){
int[] nums = new int[2];
System.out.println(nums[2]);//ArrayIndexOutOfBoundsException
return "success";
}
//该方法可以捕获本类中抛出的ArithmeticException异常以及ArrayIndexOutOfBoundsException异常
@ExceptionHandler({ArithmeticException.class,ArrayIndexOutOfBoundsException.class})
public String handlerArithmeticException(Exception e){
System.out.println(e)
return "error";
}
三、重点:添加@ExceptionHandler注解方法的形参只能是异常类型
上面的handlerArithmeticException()方法的形参不能包含其他的,只能包含Exception e这一个
,总结一下,就是有@ExceptionHandler注解的方法的形参只能是异常类型的,而且只能有这个。
异常类型🈯️Throwable及其子类
//该方法可以捕获本类中抛出的ArithmeticException异常
@ExceptionHandler({ArithmeticException.class,ArrayIndexOutofBounds.class})
public ModelAndView handlerArithmeticException(Exception e){
ModelAndView mv = new ModelAndView("error");//设置跳转的路径,error.jsp页面,前端调度器会自动添加"/",".jsp"
System.out.println(e):
mv.addobject("er", e);
return mv;
}
上面的方法使用ModelAndView做跳转
四、重点2:捕获所有方法的异常—@ControllerAdvice注解
@ExceptionHandler注解默认只能处理本类中的异常,但是在实际应用中,发生异常的方法和处理异常的方法不会在同一个类中。
我们需要写一个单独用来处理异常的类
例如:MyExceptionHandler类
添加@ControllerAdvice注解,添加该注解的类,可以捕获所有方法的异常
import org.springframework.Web.bind.annotation.ControlierAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
@ControllerAdvice
public class MyExceptionHandler{
//不是控制器,仅仅是用于处理异常的类
@ExceptionHandler({Exception.class })
public ModelAndView handlerArithmeticException2(Exception e){
ModelAndView mv = new ModelAndView("error");
System.out.println(e+"a====="+"该@ControllerAdvice中的异常处理方法")
mv.addobject("er", e);
return mv;
}
五、总结
如果是只处理当前类方法中的异常,那就在使用@ExceptionHandler注解
如果想处理所有方法的异常,要在类前面加@ControllerAdvice,并且在处理异常的类前
添加@ExceptionHandler
六、ResponseStatusExceptionResolve自定义异常显示页面
我们平常异常页面404如图
现在来自定义该页面:
通过ResponseStatusExceptionResolver类,
该类主要提供了@ResponseStatus注解,通过在类上面添加注解来定义异常处理页面,源码如下:
@ResponseStatus注解使用如下
在自定义的类MyArrayIndexOutofBoundsException上添加
填写value值先来了解HttpStatus,源码如下,可以看到是枚举类型
下面是HttpStatus部分定义:
403是页面禁止访问:Forbidden
404是找不到:Not Found
返回MyArrayIndexOutofBoundsException类来写一个403
可以写value值等于403也可以用HttpStatus.FORBIDDEN
上面两种写法意义相同
接下来定义reason,如果有方法的抛出异常MyArrayIndexOutofBoundsException,则报403错误,中文显示就是reason定义的内容:数组越界222!!!
最后一步
当前自定义的类继承Exception类
现在自定义的异常处理页面就写好了就写好了^O^/
定义一个会报异常的的方法,测试一下,刚刚自定义的异常处理页面
如果前端发来的请求中i=3,就抛出异常
MyArrayIndexOutofBoundsException
tomcat运行,访问上面那个方法,请求路径上传参用?连接i=3
运行结果:可以看到自定义定义的reason:数组越界222!!!
七、扩展@ResponseStatus 用法
定义testMyException2()方法
如果前端传来的值i=3
return “testResponseStatus”;
该返回值直接请求当前类中定义的另一个方法testResponseStatus(),注意是请求当前类中的方法!!且该方法:@RequestMapping(“testResponseStatus”),与上面返回值对应
如下图示:
我们在testResponseStatus()方法上面添加注解@ResponseStatute
完整代码如上,现在运行测试,
访问/testMyException2?i=3
运行报错,没有找到textResponseStatus.jsp页面
这里是因为前端调度器,会自动为返回值添加前缀“/”和后缀“.jsp”,
想要正确访问,需要使用redirect跳转
如下图所示
Springmvc传值和跳转可以看这篇:
Spring mvc传值和跳转
@RequestMapping("testMyException2")
public String testMyException2(@RequestParam("i") Integeri){
if(i == 3){
return "redirect:testResponseStatus”;//跳转到某一个异常处理方法里
return "success";
}
@ResponseStatus(value=HttpStatus.COWFLICT ,reason="测试。。。”)
@RequestMapping("testResponseStatus")
public String testResponseStatus(){
return "success";
}
再次运行访问路径
/testMyException2?i=3
运行结果如下:
异常页面和定义的一致
总结:
@ResponseStatus注解可以写在方法前,也可以写在类前。
异常解析:Spring mvc异常解析器与拦截器
八、其他异常处理
8.1 DefaultHandlerExceptionResolver
也是Spring mvc处理异常的是顶级接口Handler ExceptionResolver的实现类
这是一个默认处理
就是你不用写,如果有报错,会默认跳转到异常处理页面,如下所示
现在来浏览器输入
localhost:8888/SpringMVCProject/handler/welcome2
(又重新写了一个welcome5方法,所以下面截图中访问的是方法5)
可以看到异常显示页面405。
异常处理的实现类:
DefaultHandlerExceptionResolver
SPringMVC在常见异常的基础上(300 500 404),新增了一些异常,例如405—Method not Allowed,
部分源码如下:
*@see org. springframework. weh. servlet. mvc. method. annotation. ResponseEntityExceptioniandler
*@see #handleNoSuchRequestHandlingMethod
*@see #handleHttpRequestMethodNotSupported
*@see #handleHttpMediaTypeNotSupported
*@see #handleMissingServletRequestParameter
*@see #handleServletRequestBindingException
*@see #handleTypeMismatch
*@see #handleHttpMessageNotReadable
*@see #handleHttpMessageNotWritable
*@see #handleMethodArgumentNotValidException
*@see #handleMissingServletRequestParameter
*@see #handleMissingServletRequestPartException
*@see #handleBindException
8.2 SymbolMappingExceptionResolver
也是Spring mvc处理异常的是顶级接口Handler ExceptionResolver的实现类
SymbolMappingExceptionResolver通过配置实现处理异常
<!-- SimpleMappingExceptionResolver:以配置的方式处理异常-->
<bean class="org.springframework.web.servlet.handler.SimpleMappinge">
<property name="exceptionMappings">
<props>
<!--相当于catch(ArithmeticException e){ 跳转:error.jsp-->
<prop key="java.lang.ArithmeticException">
error
</prop>
</props>
</property>
</bean>
props标签中可以添加多个prop,再写一个空指针异常,如果异常,就跳转到error.jsp
<!-- SimpleMappingExceptionResolver:以配置的方式处理异常-->
<bean class="org.springframework.web.servlet.handler. SimpleMappingException">
<property name="exceptionAttribute" value="ex"></property>
<property name="exceptionMappings">
<props>
<!--相当于catch(ArithmeticException ex){跳转:error}-->
<prop key="java.lang.ArithmeticException">
error
</prop>
<prop key="java.lang.NullPointerException">
error
</prop>
</props>
</property>
</bean>
以下代码,如果捕获到异常会,异常对象会保存在exceptionAttribute的value值:ex中,并且会被放到request作用域中
<property name="exceptionAttribute" value="ex"></property>
不管捕获到的是算数异常或空指针异常,都可以通过${requestScope.ex}取值
以下error.jsp页面代码
<%@ page language="jdva" contentType="text/html; charset=UTF-8'
pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
error.jsp..<br/>
${requestScope.ex}
</body>
</html>
如果不写这行代码
<property name="exceptionAttribute" value="ex"></property>
也可以,默认exceptionAttribute的value值是exception
可以通过
${requestScope.exception}取值
tomcat运行,访问下面这个方法的算术异常
结果如下,跳转到error.jsp页面
通过${requestScope.exception}取值—>算术异常