在之前使用springmvc,异常的处理都是在controller层中进行try--catch,在springmvc种如何设置报错时跳转的页面呢?统一进行异常处理
1.配置错误视图解析器
在mvc配置文件种添加下面的配置:
<!--异常视图解析器--> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <!--默认异常视图--> <property name="defaultErrorView" value="error"/> <!--异常数据--> <property name="exceptionAttribute" value="ex"/> <!--进行细分,为定义异常返回指定的视图--> <property name="exceptionMappings"> <props> <prop key="NullPointerException"> <!--发生异常时跳转的页面--> error </prop> <prop key="ClassNotFoundException"> unauthorized </prop> </props> </property> </bean>
然后我们建一个简单的controller来验证这个视图解析器有没有起作用:
@Controller @RequestMapping("/emp") public class ExcetpionViewController { @GetMapping("/{empno}") public String fun1(@PathVariable("empno") int empno) throws ClassNotFoundException { if (empno == 5) { throw new NullPointerException("空指针异常"); } else if (empno == 4) { throw new ClassNotFoundException("找不到类异常"); } return "index"; } }
运行测试,输入不同的值,看发生异常时跳转的错误页面是否匹配;
2.在方法前面使用@ExceptionHandler注解,
该注解只能控制当前控制器汇中的异常,因此为了方便我们将其放在BaseController中,其他的controller都继承该BaseController,下面进行测试,将上一步的视图解析器注释掉:
public class BaseController { @ExceptionHandler({Exception.class}) public String exception(Exception ex, Model model) { if (ex instanceof NullPointerException) { model.addAttribute("ex", ex); return "error"; } else { return "unauthorized"; } } }
@Controller @RequestMapping("/emp") public class ExcetpionViewController extends BaseController { @GetMapping("/{empno}") public String fun1(@PathVariable("empno") int empno) throws ClassNotFoundException { if (empno == 5) { throw new NullPointerException("空指针异常"); } else if (empno == 4) { throw new ClassNotFoundException("找不到类异常"); } return "index"; } }
浏览器发送请求,测试是否跳转响应地址。
3.使用 @ControllerAdvice+ @ ExceptionHandler 注解 (推荐使用)
与上面的方式差不多,不过使用这种方式避免了继承,controller不需要再继承BaseControlelr,发生异常时,就会调用该控制器中的方法
/** * @ControllerAdvice: * 相当于是AOP,面向切面,给每一个controller都横插了该控制器 */ @ControllerAdvice public class BaseController { @ExceptionHandler({Exception.class}) public String exception(Exception ex, Model model) { if (ex instanceof NullPointerException) { model.addAttribute("ex", ex); return "error"; } else { return "unauthorized"; } } }
异步方式返回异常:
给方法添加@ResponseBody注解,返回json数据:可以定义一个实体,封装异常信息:
import lombok.Data; /** * Data注解,可以自动生成set和get方法 */ @Data public class Result { // 自定义异常状态码 private int stats; //自定义异常信息 private String messages; }
/** * @ControllerAdvice: * 相当于是AOP,面向切面,给每一个controller都横插了该控制器 */ @ControllerAdvice public class BaseController { @ExceptionHandler({Exception.class}) @ResponseBody public Result exception(Exception ex) { Result result = new Result(); if (ex instanceof NullPointerException) { result.setStats(408); result.setMessages("不能为空"); } else if (ex instanceof ClassNotFoundException) { result.setStats(409); result.setMessages("找不到类"); } return result; } }
4.实现HandlerExceptionResolver接口
@Controller @RequestMapping("/emp") public class ExcetpionViewController implements HandlerExceptionResolver { @GetMapping("/{empno}") public String fun1(@PathVariable("empno") int empno) throws ClassNotFoundException { if (empno == 5) { throw new NullPointerException("空指针异常"); } else if (empno == 4) { throw new ClassNotFoundException("找不到类异常"); } return "index"; } @Override public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { ModelAndView modelAndView = new ModelAndView(); if (ex instanceof NullPointerException) { modelAndView.addObject("ex", ex.getMessage()); modelAndView.setViewName("error"); } else { modelAndView.setViewName("index"); } return modelAndView; } }