本章节将和大家一起聊聊 Spring MVC 是如何处理异常的。
Spring MVC 框架中,将异常处理从业务逻辑中解耦出来,既保证了业务逻辑高度内聚性,又能实现了异常信息的统一处理和维护。很优雅的解决了异常的问题。通过本章节内容的学习,你将了解到 Spring MVC 内置的异常处理机制。
异常是程序运行过程中不可避免的问题。异常出现的原因很多,但不管怎样,都需要提前预知或者当异常发生后采取相应的处理措施。
异常的处理原则是:
如下面的控制器方法:
@Controller
public class ExceptionAction {
@RequestMapping("/exception01")
public String exception01(@RequestParam("userName") String userName) {
return "exception";
}
}
在浏览器中输入:http://localhost:8888/sm-demo/exception01 ,页面中会出现错误提示。
这个原因是 @RequestParam(“userName”) 注解在默认情况下,要求请求包中一定要有 userName 这个参数。
显然,页面中显示出来的错误信息是不友好的。所谓的异常处理,并不能完全阻止异常的发生。而是把异常信息对外、对内做一个封装,换一个浅白的、直接的、非专业的方式告诉使用者。
对于前面的异常解决方案,可以在 @RequestParam(value = “userName”,required = false) 中添加一个 required = false 的设置。这是一种最理想的异常解决方案。
Spring MVC 内部提供了很多优雅的异常处理机制。其中之一就是把不同的异常映射成 HTTP 状态码。
如下面实例:
@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "数字范围不符合要求!(不能是 20)")
public class NumberException extends RuntimeException {
}
@RequestMapping("/exception")
public String test(@RequestParam("num") int num) {
if (num == 20) {
throw new NumberException();
}
return "success";
}
在浏览器中输入 http://localhost:8888/sm-demo/exception?num=13 。可以看到:
定制化的信息已经有所改善,但是,还是不够友好。
Spring MVC 提供了名为 SimpleMappingExceptionResolver 的异常处理组件,该组件实现了 HandlerExceptionResolver 接口,或者说实现了这个接口的对象都可称其为全局异常处理器。
何谓全局异常处理器?
通俗讲,有点类似于前端控制器的设计思路。Spring MVC 把所有异常分离出来后通通交给全局异常处理器做集中处理。
使用流程:
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
SimpleMappingExceptionResolver simResolver=new SimpleMappingExceptionResolver();
//异常处理页面
simResolver.setDefaultErrorView("error");
//封装异常信息的属性名,默认是 exception
simResolver.setExceptionAttribute("exception");
//添加自定义异常信息
Properties mappings=new Properties();
mappings.put("com.mk.web.exception.MyException", "/WEB-INF/jsp/exception.jsp");
simResolver.setExceptionMappings(mappings);
return simResolver;
}
代码中有注解,不再多言。
public class MyException extends Exception {
public MyException() {
}
public MyException(String msg) {
super(msg);
}
}
@RequestMapping("/exception03")
public String exception03(String userName) throws MyException {
if (StringUtils.isEmpty(userName)) {
throw new MyException("用户名不能为空");
}
return "index";
}
<body>
出错啦!${exception.message}
</body>
解析出错误的具体信息,最后可以在浏览器中看到:
开发者可以根据需要编写自己的全局异常处理器组件。
Spring MVC 还可以使用注解的方式集中处理异常。
@ExceptionHandler 注解:
此注解所标注的方法能够处理同一个控制器中所有方法所抛出的异常。
如下面实例:
@ExceptionHandler(Exception.class)
public String exception() {
return "exception";
}
@RequestMapping("/exception04")
public String exception04(String userName) throws Exception {
if (StringUtils.isEmpty(userName)) {
throw new Exception("用户名不能为空");
}
return "index";
}
当控制器中的方法抛出异常后,会由 exception() 方法统一捕获,然后跳到指定页面。
@ControllerAdvice 注解:
此注解放在类的前面,且类中可以包含一个或多个如下类型的方法。
Tips: 由 @ControllerAdvice 注解标注的类本质上就是一个基于 AOP 思想的拦截器。
@ControllerAdvice 实现案例如下:
@ControllerAdvice
public class ExceptionAdviceAction {
@ExceptionHandler(Exception.class)
public String exception() {
return "exception";
}
}
无论哪一个控制器中抛出异常,都会由 ExceptionAdviceAction 类中的 exception() 方法统一响应处理。
本章节和大家讲解了 Spring MVC 中如何优雅的处理异常。主要有 3 种方案:
0/1000