目录
1、@ExceptionHandler-处理局部异常
2、HandlerExceptionResolver-处理全局异常
3、SimpleMappingExceptionResolver-处理全局异常
4、使用@ControllerAdvice+@ExceptionHandler
在 Spring MVC 应用的开发中,不管是操作底层数据库,还是业务层或控制层,都会不可避免地遇到各种可预知的、不可预知的异常。我们需要捕捉处理异常,才能保证程序不被终止。
Spring MVC 有以下 3 种处理异常的方式:
在springmvc中,异常处理的思路
上图所示,系统的dao、service、controller出现异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理。
springmvc提供全局异常处理器(一个系统只有一个异常处理器)进行统一异常处理。明白了springmvc中的异常处理机制,下面就开始分析springmvc中的异常处理。
局部异常处理仅能处理指定 Controller 中的异常。
下面使用 @ExceptionHandler 注解实现。//注意:该注解不是加在产生异常的方法上,而是加在处理异常的方法上。
定义一个处理过程中可能会存在异常情况的 submit 方法,当 i=0 时会产生算术运算异常,在同一个类中定义处理异常的方法controllerExceptionHandler,捕获运算异常。
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author swadian
* @date 2022/2/21
* @Version 1.0
*/
@Controller
@RequestMapping
public class ExceptionController {
@RequestMapping("/submit") // 抛错方法
public String submit(HttpServletRequest req,
HttpServletResponse resp) throws Exception {
String num = req.getParameter("num");
System.out.println(10 / Integer.valueOf(num));
return "success";
}
@ExceptionHandler({ArithmeticException.class}) //捕获运算异常
public String controllerExceptionHandler(Exception e) {
System.out.println("打印错误信息 ===> ArithmeticException:" + e);
// 跳转到指定页面
return "error";
}
}
异常页面 error.jsp 代码如下。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
错误页面
发生算术运算异常,请重新输入数据!
工程中web.xml配置如下
DispatcherServlet
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:springmvc-servlet.xml
1
DispatcherServlet
/
工程中springmvc-servlet.xml配置如下
整个项目的路径如下:
启动项目,访问submit方法,程序会进入到错误处理方法,最终跳转到错误页面
@ExceptionHandler 注解定义的方法优先级问题:例如发生的是 NullPointerException,但是声明的异常有 RuntimeException 和 Exception,这时候会根据异常的最近继承关系找到继承深度最浅的那个@ExceptionHandler 注解方法,即标记了 RuntimeException 的方法。
被 @ExceptionHandler 标记为异常处理方法,不能在方法中设置别的形参。但是可以使用 ModelAndView 向前台传递数据。
使用局部异常处理,仅能处理某个 Controller 中的异常,若需要对所有异常进行统一处理,可使用以下两种方法。
Spring MVC 通过 HandlerExceptionResolver 处理程序异常,包括处理器异常、数据绑定异常以及控制器执行时发生的异常。HandlerExceptionResolver 仅有一个接口方法,源码如下。
public interface HandlerExceptionResolver {
ModelAndView resolveException(HttpServletRequest var1,
HttpServletResponse var2,
Object var3,
Exception var4);
}
发生异常时,Spring MVC 会调用 resolveException() 方法,并转到 ModelAndView 对应的视图中,返回一个异常报告页面反馈给用户。
创建一个 HandlerExceptionResolver 接口的实现类 MyExceptionHandler,代码如下。
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* @author swadian
* @date 2022/2/21
* @Version 1.0
*/
@Component
public class MyExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o,
Exception e) {
Map model = new HashMap();
model.put("errorMessage", "程序运行出错");
//根据不同错误转向不同页面(统一处理),即异常与View的对应关系
if (e instanceof ArithmeticException) {
return new ModelAndView("error", model);
}
return new ModelAndView("other_error", model);
}
}
添加新的错误页面other_error.jsp如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
系统正忙页面
errorMessage:${errorMessage}
系统正忙,请稍后再试!
更改ExceptionController类,新增空指针异常
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author swadian
* @date 2022/2/21
* @Version 1.0
*/
@Controller
@RequestMapping
public class ExceptionController {
@RequestMapping("/submit") // 抛错方法
public String submit(HttpServletRequest req,
HttpServletResponse resp) throws Exception {
String num = req.getParameter("num");
System.out.println("输入的参数长度为:" + num.length());//空指针异常
System.out.println(10 / Integer.valueOf(num));
return "success";
}
}
启动项目,访问submit方法,不输入参数,程序会进入到错误处理方法,最终跳转到其他错误页面
全局异常处理可使用 SimpleMappingExceptionResolver 来实现。它将异常类名映射为视图名,即发生异常时使用对应的视图报告异常。
在 springmvc-servlet.xml 中配置全局异常,代码如下。
error
启动项目,访问submit方法,不输入参数,程序会进入到错误处理方法,最终跳转到其他错误页面
注意该方式需要开启注解支持
全局异常处理类:MyExceptionHandler.java
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
/**
* @author swadian
* @date 2022/2/21
* @Version 1.0
*/
@ControllerAdvice
public class MyExceptionHandler {
/**
* 处理异常:捕获数据运算异常
*
* @param e
* @return
*/
@ExceptionHandler({ArithmeticException.class}) //捕获所有异常 Exception.class
@ResponseBody //返回字符串而非视图
@ResponseStatus(HttpStatus.OK)
public String arithmeticExceptionHandler(Exception e) {
System.out.println("打印错误信息 ===> ArithmeticException:" + e);
//返回错误信息
return "错误信息:" + e.getMessage();
}
}
测试类
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author swadian
* @date 2022/2/21
* @Version 1.0
*/
@RestController
@RequestMapping
public class SubmitController {
//计算
@RequestMapping("/submit")
public String submit(HttpServletRequest request, HttpServletResponse response) throws Exception {
String num = request.getParameter("num");
Integer i = 10 / Integer.valueOf(num);
return "计算成功,结果为:" + i;
}
}
启动程序,参数输入为0,得到如下处理结果:
上文说到 @ ExceptionHandler 需要进行异常处理的方法必须与出错的方法在同一个 Controller里面。那么当代码加入了 @ControllerAdvice,则不需要必须在同一个controller 中了。
这也是 Spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。
也就是说,@controlleradvice + @ ExceptionHandler 也可以实现全局的异常捕捉。 请确保此WebExceptionHandle 类能被扫描到并装载进 Spring 容器中。
若在其他的由@Controller标记的Handler类中的Handle方法抛出异常,且没有在Handler类中定义@ExceptionHandler方法,则会去由@ControllerAdvice标记的类中去找,若也找不到,则在页面抛出异常。
问题:Tomcat方式启动和Application方式启动有什么区别呢?
https://www.jb51.net/article/211409.htm