本文记录我在学习过程中对于SpringBoot处理异常的两种方式的理解
1. 实现HandlerExceptionResolver接⼝,定义全局异常处理器。
package com.lxs.demo.demos.exception;
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;
@Component
public class CustomHandlerExceptionResolver implements HandlerExceptionResolver {
@Override
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
e.printStackTrace();
CustomException ce = null;
if (e instanceof CustomException) {
ce = (CustomException) e; //自定义异常
} else if (e instanceof NullPointerException) {
ce = new CustomException("空指针异常,请联系管理员处理...");
} else {
ce = new CustomException("其他系统异常,请联系管理员处理...");
}
ModelAndView mv = new ModelAndView();
e.getMessage(); //${e.message}
mv.addObject("e", ce);
mv.setViewName("error");
return mv;
}
}
继承了 HandlerExceptionResolver,,捕获这个异常,
然后判断这个异常的类型,
第一个是自定义异常,第二个是空指针异常,剩下的就是其他的异常
在判断完这个异常后,我这里把它存到了model里面
然后我做了一个转发,跳转到了error.jsp这个页面,这是error.jsp的页面内容,来显示e.message
下面就来进行一下测试
我写了个index.html页面 和TestController,这是代码
package com.lxs.demo.demos.web;
import com.lxs.demo.demos.exception.CustomException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/one")
public String one() {
String s = null;
s.trim(); //空指针异常
return "success";
}
@RequestMapping("/two")
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public String two(String name) throws Exception {
if ("tom".equals(name)) {
throw new CustomException("用户名重复的自定义异常");
}
return "success";
}
@RequestMapping("/three")
public String three() throws Exception {
String[] s = {"a", "b", "c"};
s[4] = "123";
return "success";
}
/one /two /three分别代表空指针,用户名重复,数组越界异常
接下来启动项目访问index.html
分别访问one,two,three出现如下页面
2.@ControllerAdvice + @ExceptionHandler,ControllerAdvice对于Controller增强
ExceptionHandler这个注解跟ModelAttribute很像,
@ModelAttribute这个注解是在所有的方法执行之前执行
@ExceptionHandler是在所有方法发生异常时执行
下面测试一下,这是我的TestController代码
package com.lxs.demo.demos.web;
import com.lxs.demo.demos.exception.CustomException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@Controller
@RequestMapping("/test")
public class TestController {
@RequestMapping("/one")
public String one() {
String s = null;
s.trim(); //空指针异常
return "success";
}
@RequestMapping("/two")
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public String two(String name) throws Exception {
if ("tom".equals(name)) {
throw new CustomException("用户名重复的自定义异常");
}
return "success";
}
@RequestMapping("/three")
public String three() throws Exception {
String[] s = {"a", "b", "c"};
s[4] = "123";
return "success";
}
@ExceptionHandler({CustomException.class}) //捕获运算异常
public String controllerExceptionHandler(CustomException e, Model model) {
System.out.println("打印错误信息 自定义错误 ===> :" + e);
// 跳转到指定页面
return "error";
}
@ExceptionHandler({NullPointerException.class}) //捕获运算异常
public String controllerExceptionHandler(NullPointerException e) {
System.out.println("打印错误信息 空指针错误 ===> :" + e);
// 跳转到指定页面
return "error";
}
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map errorHandler(Exception ex) {
Map map = new HashMap();
map.put("code", 400);
map.put("msg", ex.getMessage());
return map;
}
}
@ExceptionHanlder对于不同的异常做了不同的处理
下面来测试一下
上文的index.html页面不变,继续访问
访问one
此时控制台打印空指针异常
访问其他的同理,就不一一展示了
此时会发现一个问题,
@ExceptionHandler只会对当前的处理器进行处理,那么应该怎么做到全局呢
所以此时需要配合@ControllerAdvice使用
ControllerAdvice对于Controller增强,对所有的Controller都适用
这时写了一个类,这是代码
package com.lxs.demo.demos.exception;
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;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class MyControllerAdvice {
/**
* 全局异常捕捉处理
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map errorHandler(Exception ex) {
Map map = new HashMap();
map.put("code", 400);
map.put("msg", ex.getMessage());
return map;
}
/**
* 空指针异常
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = NullPointerException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Map errorNullHandler(NullPointerException ex) {
Map map = new HashMap();
map.put("code", 300);
map.put("msg", "空指针异常");
return map;
}
/**
* 全局捕捉自定义异常(凡是抛出CustomException的异常都会走这里)
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = CustomException.class)
public Map myErrExceptionHandler(CustomException ex) {
Map map = new HashMap();
map.put("code", 500);
map.put("msg", ex.getMessage());
return map;
}
}
这就是一个全局异常处理器
下面来测试一下,我把TestController中的ExceptionHandler全部注释掉
再打开网页测试一下,在访问如图所示
好了,说到这里差不多就结束,只要把这两种方式弄清楚就行