1. SpringMVC异常处理
在SpringMVC框架中,异常的处理分为预期异常和运行时异常,预期异常通过需要通过捕获来获取异常信息,运行时异常就靠我们程序员进行代码规范啦。
系统中一般有 Dao 层、Service 层、Controller 层,通过 throws exception
一层一层往上抛出,最后由 DispatchServlet 中方法 doDispatch
进行捕获交由异常处理器处理。Spring MVC 异常处理详解
2. SpringMVC异常处理三种方式
在SpringMVC中有三种处理 Controller 抛出的异常的方式。第一种是实现 HandlerExceptionResolver ;第二种是使用 @ExceptionHandler;第三种是使用 @ControllerAdvice + @ExceptionHandler。每种方法各有各的优缺点。下面我们一种一种的来说明。
2.1 实现 HandlerExceptionResolver 异常处理
这种方式可以用来进行全局的异常控制。具体步骤是:
2.1.1 编写自定义的异常类
package com.ssm.exception;
/**
* 描述:自定义异常类
* @author lytao123
*
*/
public class CustomException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public CustomException(String message) {
super(message);
this.message = message;
}
// 异常信息
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
2.1.2 编写自定义的异常处理器
这里需要实现 HandlerExceptionResolver 接口
package com.ssm.controller.exceptionresolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import com.ssm.exception.CustomException;
public class CustomExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex) {
ex.printStackTrace();
CustomException customException = null;
//如果抛出的是系统自定义异常则直接转换
if(ex instanceof CustomException){
customException = (CustomException)ex;
}else{
//如果抛出的不是系统自定义异常则重新构造一个未知错误异常。
customException = new CustomException("未知错误,请与系统管理员联系!");
}
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("message", customException.getMessage());
modelAndView.setViewName("error");
return modelAndView;
}
}
2.1.3 配置自定义的异常处理器
在 springmvc.xml 中配置:
<!-- 全局异常处理器 -->
<bean id="handlerExceptionResolver" class="com.ssm.controller.exceptionresolver.CustomExceptionResolver"/>
2.1.4 测试
在 Controller 中编写代码抛出异常:
private final static String SUCCESS = "success"; //返回结果
private final static String ERROR = "error"; //返回结果
//方式一 继承 HandlerExceptionResolver
//测试捕获全局异常
@RequestMapping(value="/testException",method=RequestMethod.GET)
public ModelAndView testException() throws Exception {
ModelAndView modelAndView = new ModelAndView();
if(!"".equals(SUCCESS)) {
//抛出异常
throw new CustomException("测试异常捕获方式一。");
}
modelAndView.setViewName(SUCCESS);
return modelAndView;
}
页面跳转到 error.jsp 页面,打印出 “发生错误。测试异常捕获方式一。”
2.2 使用 @ExceptionHandler 异常处理
这种方式的异常处理因为 改注解只能注解到方法上,所以进行异常处理的方法必须与出错的方法在同一个 Controller 里面,这就造成了这种方法不好运用在全局的异常控制上,如果想实现需要每个 Controller 都写一个方法,一般用来对 Controller 的特定异常控制。
2.2.1 编写一个自定义的异常类
代码如下:
package com.ssm.exception;
/**
* @Description 自定义异常类
* @author 欧阳
* @since 2018年12月15日 下午8:43:42
* @version V1.0
*/
public class MyException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public MyException(String message) {
super(message);
}
}
2.2.2 编写异常处理方法及测试方法
/**
* 方式二,@ExceptionHandler 可用来捕获单个Controller中的异常
* @param e
* @return
*/
//用于处理异常
@ExceptionHandler(value={MyException.class})
public /*@ResponseBody*/ String exception(Exception e) {
System.out.println(e.getMessage());
return ERROR;
// return e.getMessage();
}
@RequestMapping("/testException2")
public ModelAndView testException2() throws Exception {
ModelAndView modelAndView = new ModelAndView();
if(!"".equals(SUCCESS)) {
throw new MyException("测试错误,方式二");
}
modelAndView.setViewName(SUCCESS);
return modelAndView;
}
注意:这里被 @ExceptionHandler 注解标注的方法的参数只能是 Exception 。
页面跳转到 error.jsp 页面,打印出 “发生错误。“
2.3 使用 @ControllerAdvice + @ExceptionHandler 异常处理
这种方式的优点是将 Controller 层的异常和数据校验的异常进行统一处理,减少编码量,提升扩展性和可维护性。缺点是只能处理 Controller 层未捕获(往外抛)的异常,对于 Interceptor(拦截器)层的异常和Spring 框架层的异常就不能捕获到。具体使用方法如下:
新建 GlobalExceptionHandler类,同时要保证能被扫描到并装载进 Spring 容器中,并使用注解 @ControllerAdvice 标注,在其中的方法使用注解 @ExceptionHandler 标注,如下代码所示,可定义多个方法,使用多个 @ExceptionHandler 注解不同类型的异常。
package com.ssm.controller.exceptionresolver;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* @Description 实现全局的 Controller 层的异常处理,要保证能被扫描到并装载进 Spring 容器中。
* @author 欧阳
* @since 2018年12月15日 下午9:00:35
* @version V1.0
*/
@ControllerAdvice
public class GlobalExceptionHandler {
/**
* 处理所有不可知的异常
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
public @ResponseBody String handleException(Exception e){
return "Exception! thrid";
}
}