您的位置 首页 java

「Web开发」Spring MVC 中的异常处理方法

简概

官方文档地址: HTML /web.html#mvc-ann- Exception handler

异常处理⽅法

  • 处理⽅法
    • @Exception handler
  • 添加位置
    • @Controller / @RestController
    • @ControllerAdvice / @RestControllerAdvice
  1. @RestControllerAdvice或者@ControllerAdvice类内的解析器的优先级低于@ Controller或@RestController 类的解析器的优先级
  2. 如果一个异常能被多个解析器所处理,则选择继承关系最近的解析器

异常处理方法-@ExceptionHandler

@Controller和@ControllerAdvice类可以有@ExceptionHandler方法来处理来自 控制器 方法的异常,如下例所示:

 @Controller
public class SimpleController {

    // ...

    @Exception handle r
    public ResponseEntity<String> handle(IOException ex) {
        // ...
    }
}  

异常可以匹配正在传播的顶级异常(例如抛出的直接IOException),也可以匹配包装器异常中的嵌套原因(例如包裹在Illegal State Exception中的IOException)。 在5.3中,这可以匹配任意的原因级别,而以前只考虑直接原因

为了匹配异常类型,最好将目标异常声明为方法参数 ,如上例所示。当多个异常方法匹配时,根异常匹配通常优先于原因异常匹配。更具体地说, ExceptionDepthComparator用于根据抛出异常类型的深度对异常进行排序

或者,通过注解的声明来缩小异常类型以匹配,如下例所示:

 @ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(IOException ex) {
    // ...
}  

甚至可以使用一个带有非常通用的参数签名的特定异常类型列表,如下例所示:

 @ExceptionHandler({FileSystemException.class, RemoteException.class})
public ResponseEntity<String> handle(Exception ex) {
    // ...
}  

根源异常和原因异常匹配之间的区别可能令人惊讶。

在前面展示的IOException变体中,通常使用实际的FileSystemException或RemoteException实例作为参数调用该方法,因为它们都是从IOException扩展而来的。但是,如果任何这样的匹配异常在包装器异常中传播,而包装器异常本身就是一个IOException,则传入的异常实例就是那个包装器异常。

handle (Exception)变体中,这种行为甚至更简单。在包装场景中,这总是与包装器异常一起调用,在这种情况下,通过ex.getCause()找到实际匹配的异常。传入的异常只有在作为顶级异常抛出时才是实际的FileSystemException或RemoteException实例。

通常建议在参数签名中尽可能具体,以减少根源异常类型和原因异常类型之间不匹配的可能性。 考虑将多匹配方法分解为单独的@ExceptionHandler方法,每个方法通过其签名匹配单个特定的异常类型。

在多个@ControllerAdvice中,建议按相应顺序优先级排列的@ControllerAdvice上声明主根异常映射。虽然根异常匹配优先于原因,但这是在一个给定 controller 或@ControllerAdvice类的方法中定义的。这也就是说 高优先级的@ControllerAdvice Bean 上的原因匹配优先于低优先级的@ControllerAdvice bean上的任何匹配 (例如,根)。

最后但并非最不重要的是,@ExceptionHandler方法实现可以通过以原始形式重新抛出给定异常实例来选择退出处理。如果您只对根级匹配感兴趣,或者对无法静态确定的特定上下文中的匹配感兴趣,那么这将非常有用。 重新抛出的异常通过剩余的解析链传播,就好像给定的@ExceptionHandler方法一开始就不匹配一样

Spring MVC 中对@ExceptionHandler方法的支持是建立在DispatcherServlet级别、HandlerExceptionResolver机制上的。

Controller Advice

官网文档:#mvc-ann-controller-advice

@ExceptionHandler、@ Init Binder和@ModelAttribute三个注解标记的方法只作用于声明它们的@Controller 或类层次结构。而 如果它们在@ControllerAdvice或@RestControllerAdvice类中声明,那么它们将应用于任何controller 。从5.3开始,@ControllerAdvice中的@ExceptionHandler方法可以用于处理来自任何@Controller或任何其他处理程序的异常。

@ControllerAdvice使用@Component进行元注释,因此可以通过组件扫描注册为 spring bean。@RestControllerAdvice使用@ControllerAdvice和@ResponseBody进行元注释,这意味着@ExceptionHandler方法的返回值将通过响应体消息转换呈现,而不是通过HTML视图。

在启动时, Request MappingHandlerMapping和ExceptionHandlerExceptionResolver检测 controller advice beans 并在运行时应用它们。来自@ControllerAdvice的全局@ExceptionHandler方法应用在来自@Controller的本地方法之后。相比之下,全局的@ModelAttribute和@InitBinder方法在本地方法之前被应用。

@ControllerAdvice注解具有一些属性,可以缩小@ControllerAdvice注解所应用的控制器和处理程序集。

「Web开发」Spring MVC 中的异常处理方法

但其是在运行时计算,如果广泛使用,可能会对性能产生负面影响。

@InitBinder

@InitBinder 用于在控制器( Controller) 中标注于方法上,表示为当前控制器注册一个属性编辑器,只对当前的Controller有效。 @InitBinder 标注的方法必须有一个参数 WebDataBinder 。webDataBinder是用于表单到方法的数据绑定的。所谓的属性编辑器可以理解就是帮助我们完成参数绑定。

可参考:

@ModelAttribute

@ModelAttribute,用来将请求参数绑定到 Model 对象。
需要注意的是,因为模型对象要先于 controller 方法之前创建,所以 被 @ModelAttribute 注解的方法会在 Controller 每个方法执行之前都执行 。因此 一个 Controller 映射多个 URL 时,要谨慎使用

可参考:

@Exception Handler 支持的方法参数

方法参数

描述

Exception type

用于访问引发的异常。

HandlerMethod

用于访问引发异常的控制器方法。

WebRequest, NativeWebRequest

对请求参数、请求和会话属性的通用访问,而不直接使用Servlet API。

javax .servlet.ServletRequest, javax. Servlet .ServletResponse

选择任何特定的请求或响应类型(例如,ServletRequest或HttpServletRequest或Spring的MultipartRequest或MultipartHttpServletRequest)。

javax.servlet.http.HttpSession

强制会话的存在。因此,这样的参数永远不会为空。
注意,会话访问不是 线程 安全的。如果允许多个请求并发访问一个会话,可以考虑将RequestMappingHandlerAdapter实例的synchronizeOnSession标志设置为true。

java .security.Principal

当前经过身份验证的用户——如果知道,可能是特定的Principal实现类。

HttpMethod

请求的HTTP方法。

java.util. Locale

当前请求区域设置,由可用的最具体的LocaleResolver确定——实际上,配置的LocaleResolver或LocaleContextResolver。

java.util.TimeZone, java.time.ZoneId

与当前请求关联的时区,由LocaleContextResolver确定。

java.io.OutputStream, java.io.Writer

用于访问由Servlet API公开的原始响应体

java.util.Map, org.springframework.ui.Model, org.springframework.ui.ModelMap

以访问错误响应的模型。总是空的。

RedirectAttributes

指定在重定向-情况下使用的属性(将被附加到查询字符串)和 flash 属性将被临时存储,直到重定向后的请求。参见 重定向属性 Flash属性

@SessionAttribute

对于任何会话属性的访问,与作为类级别@ Session Attributes声明的结果存储在会话中的模型属性相反。更多细节请参见 @SessionAttribute

@RequestAttribute

用于访问请求属性。详见 @RequestAttribute

@ExceptionHandler支持的方法返回值

@ResponseBody

返回值通过HttpMessageConverter实例转换并写入响应。参见 @ResponseBody

HttpEntity<B>, ResponseEntity<B>

返回值指定完整的响应(包括HTTP头和正文)通过HttpMessageConverter实例进行转换并写入响应。参见 ResponseEntity

String

用ViewResolver实现解析并与隐式模型一起使用的视图名称——通过 command 对象和@ModelAttribute方法确定。 handler 方法还可以通过声明model参数(前面描述过)以编程方式丰富模型。

View

一个视图实例,用来与隐式模型一起渲染——通过 command 对象和@ModelAttribute方法确定。 handler 方法还可以通过声明model参数(前面描述过)以编程方式丰富模型。

java.util.Map, org.springframework.ui.Model

属性要添加到隐式模型中,视图名称通过RequestToViewNameTranslator隐式确定。

@ModelAttribute

要添加到模型中的属性,通过RequestToViewNameTranslator隐式确定视图名称。
注意,@ModelAttribute是可选的。参见该表末尾的“ Any other return value ”。

ModelAndView object

要使用的视图和模型属性,以及可选的响应状态。

void

具有void返回类型(或空返回值)的方法如果还具有ServletResponse、 OutputStream 参数或@ResponseStatus注解,则被认为已经完全处理了响应。如果 controller 已经做了一个 positive 的ETag或lastModified时间戳检查,也会发生同样的情况(详见 Controllers )。
如果以上都不是true,void返回类型也可以为 REST controllers 指示“无响应体”,或为 HTML controllers 指示默认视图名称选择。

Any other return value

如果返回值与上述任何一个都不匹配,并且不是简单类型(由 BeanUtils#isSimpleProperty 确定),默认情况下,它被视为要添加到模型中的模型属性。如果是简单类型,则仍然无法解决。

文章来源:智云一二三科技

文章标题:「Web开发」Spring MVC 中的异常处理方法

文章地址:https://www.zhihuclub.com/182995.shtml

关于作者: 智云科技

热门文章

网站地图