一、简要说明

如何实现网上文章基本是随便一搜就可以很快找到, 这里不再赘述.

二、Spring-web和Spring-webmvc

通过idea查看到两个注解位于 spring-web-5.2.2.RELEASE.jar包内,.

而这里maven依赖有spring web 和spring webmvc 两个包;

查询到spring web主要提供了HTTP的功能集成,

而spring-webmvc基于spring-web, 从而提供servlet功能. (参考: Maven dependency spring-web vs spring-webmvc)

2.2.5 Web

The Web layer consists of the spring-web, spring-webmvc, spring-websocket, and spring-webmvc-portlet modules.

The spring-web module provides basic web-oriented integration features such as multipart file upload functionality and the initialization of the IoC container using Servlet listeners and a web-oriented application context. It also

contains an HTTP client and the web-related parts of Spring’s remoting support.

The spring-webmvc module (also known as the Web-Servlet module) contains Spring’s model-view-controller (MVC) and REST Web Services implementation for web applications. Spring’s MVC framework provides a clean > separation between domain model code and web forms and integrates with all of the other features of the Spring Framework.

The spring-webmvc-portlet module (also known as the Web-Portlet module) provides the MVC implementation to be used in a Portlet environment and mirrors the functionality of the Servlet-based spring-webmvc module.

三、两个注解

我们已经知道主要使用@ControllerAdvice@ExceptionHandler这两个注解来实现全局异常类的定义.

  • @ControllerAdvice
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {}; @AliasFor("value")
String[] basePackages() default {}; Class<?>[] basePackageClasses() default {}; Class<?>[] assignableTypes() default {}; Class<? extends Annotation>[] annotations() default {};
}
  • @ExceptionHandler
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
Class<? extends Throwable>[] value() default {};
}

通过在spring framework - web mvc官方文档中搜索@ControllerAdvice 得到了一些信息:

(以下部分摘自Spring文档)

  • Resolves exceptions by invoking an @ExceptionHandler method in a @Controller or a @ControllerAdvice class. See @ExceptionHandler methods.

1.3.6. Exceptions (@ExceptionHandler methods)

文档中说"@Controller和@ControllerAdvice类可以具有 @ExceptionHandler处理控制器方法异常的方法", 但是经过尝试发现@Controller和@ExceptionHandler组合并没有实现.

  • 两种匹配异常的方式

  • 直接匹配

该异常可能与正在传播的顶级异常(即,直接IOException引发的异常)匹配,也可能与顶级包装器异常(例如,IOException包装在中IllegalStateException)的直接原因匹配 。

对于匹配的异常类型,如前面的示例所示,最好将目标异常声明为方法参数。当多个异常方法匹配时,根源异常匹配通常比原因异常匹配更可取。更具体地,ExceptionDepthComparator用于根据异常从引发的异常类型的深度对异常进行排序。

    @ExceptionHandler
public ResponseEntity<String> handle(IOException ex) {
// ...
}
  • 注释声明可以缩小异常类型以使其匹配,如以下示例所示:
@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优先级并以相应顺序声明您的主根异常映射。尽管根异常匹配优先于原因,但这是在给定控制器或@ControllerAdvice类的方法之间定义的。这意味着优先级较高的@ControllerAdvicebean 上的原因匹配优于优先级 较低的@ControllerAdvicebean 上的任何匹配(例如,根) 。

  • 最后但并非最不重要的一点是,@ExceptionHandler方法实现可以选择通过以原始形式重新抛出异常来退出处理给定异常实例。在仅对根级别匹配或无法静态确定的特定上下文中的匹配感兴趣的情况下,这很有用。重新抛出的异常会在其余的解决方案链中传播,就像给定的@ExceptionHandler方法最初不会匹配一样。

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

  • @ExceptionHandler 支持的方法参数:(见原文)
  • @ExceptionHandler 方法支持的返回值:(见原文)

REST API exceptions

REST服务的常见要求是在响应正文中包含错误详细信息。Spring框架不会自动执行此操作,因为响应主体中错误详细信息的表示是特定于应用程序的。但是,a @RestController可以使用@ExceptionHandler带有ResponseEntity返回值的方法来设置响应的状态和主体。也可以在@ControllerAdvice类中声明此类方法以将其全局应用。

在响应主体中实现具有错误详细信息的全局异常处理的应用程序应考虑extend ResponseEntityExceptionHandler,它提供对Spring MVC引发的异常的处理,并提供用于自定义响应主体的钩子。要使用此功能,请创建一个的子类 ResponseEntityExceptionHandler,用对其进行注释@ControllerAdvice,覆盖必要的方法,然后将其声明为Spring bean。

1.3.7. Controller Advice

通常@ExceptionHandler,,@InitBinder和@ModelAttribute方法适用于@Controller声明它们的类(或类层次结构)。如果要使此类方法更全局地应用(跨控制器),则可以在带有@ControllerAdvice或注释的类中声明它们@RestControllerAdvice。

@ControllerAdvice带有注释@Component,这意味着可以通过组件扫描将此类注册为Spring Bean 。@RestControllerAdvice是用@ControllerAdvice和注释的组合注释@ResponseBody,从本质上讲,这意味着 @ExceptionHandler方法是通过消息转换(与视图解析或模板渲染相比)呈现给响应主体的。

在启动时,用于@RequestMapping和@ExceptionHandler 方法的基础结构类会检测带有注释的Spring bean @ControllerAdvice,然后在运行时应用其方法。全局@ExceptionHandler方法(来自@ControllerAdvice)适用于局部方法(来自@Controller)。相比之下,全局@ModelAttribute 和@InitBinder方法先于局部方法。

默认情况下,@ControllerAdvice方法适用于每个请求(即所有控制器),但是您可以通过使用批注上的属性将其范围缩小到控制器的子集,如以下示例所示:

// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {} // Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {} // Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}

前面示例中的选择器在运行时进行评估,如果广泛使用,可能会对性能产生负面影响。有关@ControllerAdvice 更多详细信息,请参见 javadoc。

自定义Springboot全局异常类的更多相关文章

  1. Asp.net Core WebApi 全局异常类

    通过全局异常类,所有程序中遇到的错误都会被拦截,并友好的返回结果. 1.自定义一个全局异常处理类中间件 using Microsoft.AspNetCore.Http; using Newtonsof ...

  2. springBoot 全局异常方式处理自定义异常 @RestControllerAdvice + @ExceptionHandler

    前言 本文讲解使用 @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理,可以处理大部分开发中用到的自自定义业务异常处理了,再也不用 ...

  3. SpringBoot全局异常拦截

    SpringBoot全局异常捕获 使用到的技能 @RestControllerAdvice或(@ControllerAdvice+@ResponseBody) @ExceptionHandler 代码 ...

  4. SpringBoot 全局异常配置

    在日常web开发中发生了异常,往往是需要通过一个统一的异常处理来保证客户端能够收到友好的提示. 一.默认异常机制 默认异常处理(SpringBoot 默认提供了两种机制,一种是针对于web浏览器访问的 ...

  5. springboot 全局异常捕获,异常流处理业务逻辑

    前言 上一篇文章说到,参数校验,往往需要和全局的异常拦截器来配套使用,使得返回的数据结构永远是保持一致的.参数异常springboot默认的返回结构: { "timestamp": ...

  6. [spring-boot] ControllerAdvice异常类

    package com.example.demo.exception; import org.springframework.web.bind.annotation.ControllerAdvice; ...

  7. springboot全局异常封装案例

    @ControllerAdvice三个场景:>https://www.cnblogs.com/lenve/p/10748453.html 全局异常处理 全局数据绑定 全局数据预处理 首先定义一个 ...

  8. springboot全局异常拦截源码解读

    在springboot中我们可以通过注解@ControllerAdvice来声明一个异常拦截类,通过@ExceptionHandler获取拦截类抛出来的具体异常类,我们可以通过阅读源码并debug去解 ...

  9. spring自定义controller全局异常拦截

    --异常类可以按需要自定义package com.dhht.wechat.exception; import com.alibaba.fastjson.JSONObject;import org.sp ...

随机推荐

  1. Splay代码简化版

    皆さん.こんにちは.上一篇文章,我们讲了Splay如何实现.这一篇我们来让我们的伸展树短一点. 上一篇Splay讲解的链接:リンク. 首先还是变量的定义,在这里呢,我把一些小函数也用Define来实现 ...

  2. C#/WPF/WinForm/.NET程序代码实现软件程序开机自动启动的两种常用方法的示例与源码下载带详细注释-源码代码-注册表方式-启动目录快捷方式

    C#/WPF/WinForm/.NET程序代码实现软件程序开机自动启动的两种常用方法的示例与源码下载带详细注释-源码代码-注册表方式-启动目录快捷方式 C#实现自动启动的方法-两种方法 源码下载地址: ...

  3. Java实现 LeetCode 809 情感丰富的文字 (暴力)

    809. 情感丰富的文字 有时候人们会用重复写一些字母来表示额外的感受,比如 "hello" -> "heeellooo", "hi" ...

  4. (Java实现) 洛谷 P1028 数的计算

    题目描述 我们要求找出具有下列性质数的个数(包含输入的自然数nn): 先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理: 不作任何处理; 在它的左边加上一个自然数,但该自然数不能 ...

  5. Java实现 LeetCode 710 黑名单中的随机数(黑白名单)

    710. 黑名单中的随机数 给定一个包含 [0,n ) 中独特的整数的黑名单 B,写一个函数从 [ 0,n ) 中返回一个不在 B 中的随机整数. 对它进行优化使其尽量少调用系统方法 Math.ran ...

  6. Java实现 LeetCode 110 平衡二叉树

    110. 平衡二叉树 给定一个二叉树,判断它是否是高度平衡的二叉树. 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1. 示例 1: 给定二叉树 [3,9 ...

  7. Java GUI 键盘事件

    import java.awt.FlowLayout; import java.awt.Frame; import java.awt.TextField; import java.awt.event. ...

  8. Java实现蓝桥杯正则问题

    题目描述 考虑一种简单的正则表达式: 只由 x ( ) | 组成的正则表达式. 小明想求出这个正则表达式能接受的最长字符串的长度. 例如 ((xx|xxx)x|(x|xx))xx 能接受的最长字符串是 ...

  9. java实现第六届蓝桥杯立方体自身

    立方变自身 题目描述 观察下面的现象,某个数字的立方,按位累加仍然等于自身. 1^3 = 1 8^3 = 512 5+1+2=8 17^3 = 4913 4+9+1+3=17 - 请你计算包括1,8, ...

  10. docker-compose mysql和node连接认证mongo问题

    前言 最近,想部署一个自己的项目,鉴于自己的服务器是VPS(虚拟主机),配置也不够,就想到了用 docker 直接部署好了,这样既方便部署也方便不用的时候卸载或更新 然后本地搭建了环境,踩了一些坑,在 ...