基于@RestControllerAdvice与@ControllerAdvice的区别说明

 更新时间:2021年09月25日 15:12:47   作者:y_bccl27  
这篇文章主要介绍了@RestControllerAdvice与@ControllerAdvice的区别说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

@RestControllerAdvice与@ControllerAdvice的区别

@RestControllerAdvice注解与@ControllerAdvice注解位于同一个依赖包下面,其pom依赖为:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>5.3.3</version>
</dependency>

有时会发现在不同的项目中,全局异常处理部分,有的自定义类添加@RestControllerAdvice注解,有的自定义类添加@ControllerAdvice注解。

其实这两个注解的作用基本上是一致的,都是为了实现自定义全局异常处理,

唯一的区别是:@RestControllerAdvice注解包含了@ControllerAdvice注解和@ResponseBody注解。

@ControllerAdvice注解的源码为

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice { 
}

@RestControllerAdvice注解的源码为

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ControllerAdvice
@ResponseBody
public @interface RestControllerAdvice { 
}

当自定义类加@ControllerAdvice注解时,方法需要返回json数据时,每个方法还需要添加@ResponseBody注解

当自定义类加@RestControllerAdvice注解时,方法自动返回json数据,每个方法无需再添加@ResponseBody注解

/**
 * 全局异常处理类
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
 
 @ExceptionHandler(Exception.class)
 public Result<String> ExceptionHandler(Exception e) {
  log.error("出现异常:", e);
  return Result.failed(e.getMessage());
 }
}

@RestControllerAdvice @ControllerAdvice注解无效 通用异常处理

简单记录下,今天打算写一个公共异常处理切面,主要是将所有抛出的异常拦截,然后返回给前端的时候,统一是错误码,错误原因等。防止直接在前端抛出错误。

@RestControllerAdvice 或者 @ControllerAdvice 可以直接作为错误处理的切面对待。但是使用过程中发现这两个注解无效,原因是我将GlobalExceptionHandler定义在另一个包里面,@SpringBootApplication无法自动加载到该注解(springboot启动类的默认扫描路径是该类所在的包下面的所有java类。

如:启动类在“com.galen.cloud.portal”包下,那么只有com.galen.cloud.portal包下的类会被扫描加载)。所以添加上对应的scanBasePackages 即可(我这边改为扫描所有匹配com.galen.*的包):

启动类

package com.galen.cloud.portal;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = "com.galen.*")
public class galenPortalApplication {
    public static void main(String[] args) {
        SpringApplication.run(galenPortalApplication.class, args);
    }
}

错误处理类

package com.galen.common.exception;
import com.galen.common.core.domain.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
 * 异常处理器
 * @author galen
 */
@RestControllerAdvice
public class GlobalExceptionHandler
{
    private Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 请求方式不支持
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    @ResponseStatus(code = HttpStatus.METHOD_NOT_ALLOWED)
    public R handleException(HttpRequestMethodNotSupportedException e)
    {
        logger.error(e.getMessage(), e);
        return R.error("不支持' " + e.getMethod() + "'请求");
    }
    /**
     * 拦截未知的运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public R notFount(RuntimeException e)
    {
        if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null)
        {
            throw e;
        }
        logger.error("运行时异常:", e);
        return R.error("运行时异常:" + e.getMessage());
    }
    /**
     * 处理自定义异常
     */
    @ExceptionHandler(galenException.class)
    public R handleWindException(galenException e)
    {
        return R.error(e.getCode(), e.getMessage());
    }
    @ExceptionHandler(DuplicateKeyException.class)
    public R handleDuplicateKeyException(DuplicateKeyException e)
    {
        logger.error(e.getMessage(), e);
        return R.error("数据库中已存在该记录");
    }
    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) throws Exception
    {
        logger.error(e.getMessage(), e);
        return R.error("服务器错误,请联系管理员");
    }
    /**
     * 捕获并处理未授权异常
     *
     * @param e 授权异常
     * @return 统一封装的结果类, 含有代码code和提示信息msg
     */
    @ExceptionHandler(UnauthorizedException.class)
    public R handle401(UnauthorizedException e)
    {
        return R.error(401, e.getMessage());
    }
    // 验证码错误
    @ExceptionHandler(ValidateCodeException.class)
    public R handleCaptcha(ValidateCodeException e)
    {
        return R.error(e.getMessage());
    }
}

最后拦截效果图如下:

在这里插入图片描述

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 微服务间调用Retrofit在Spring Cloud Alibaba中的使用

    微服务间调用Retrofit在Spring Cloud Alibaba中的使用

    这篇文章主要为大家介绍了微服务间调用Retrofit在Spring Cloud Alibaba中的使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • 一文搞懂Java中的序列化与反序列化

    一文搞懂Java中的序列化与反序列化

    序列化是将对象转换成二进制字节流的过程;反序列化是从二进制字节流中恢复对象的过程。文中降通过示例详解二者的使用与区别,需要的可以参考一下
    2022-08-08
  • 详细聊聊JDK中的反模式接口常量

    详细聊聊JDK中的反模式接口常量

    这篇文章主要给大家介绍了关于JDK中反模式接口常量的相关资料,文中通过实例代码介绍的非常详细,对大家学习或者使用jdk具有一定的参考学习价值,需要的朋友可以参考下
    2022-01-01
  • Spring MVC温故而知新系列教程之从零开始

    Spring MVC温故而知新系列教程之从零开始

    Spring MVC 框架在 Java 的 Web 项目中应该是无人不知的吧,你不会搭建一个 Spring 框架?作为身为一个刚刚学习Java的我都会,如果你不会的话,那可真令人忧伤。下面这篇文章主要给大家介绍了关于Spring MVC从零开始的相关资料,需要的朋友可以参考下
    2018-05-05
  • Mybatis-flex整合达梦数据库的实现示例

    Mybatis-flex整合达梦数据库的实现示例

    本文讨论了国产达梦数据库与Mybatis-flex框架的整合过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-10-10
  • 基于Mybatis-Plus的CRUD的实现

    基于Mybatis-Plus的CRUD的实现

    这篇文章主要介绍了基于Mybatis-Plus的CRUD的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-11-11
  • spring boot自动装配之@ComponentScan注解用法详解

    spring boot自动装配之@ComponentScan注解用法详解

    @ComponentScan的作用就是根据定义的扫描路径,把符合扫描规则的类装配到spring容器中,下面这篇文章主要给大家介绍了关于spring boot自动装配之@ComponentScan注解用法的相关资料,需要的朋友可以参考下
    2023-04-04
  • SpringBoot如何通过devtools实现热部署

    SpringBoot如何通过devtools实现热部署

    这篇文章主要介绍了SpringBoot如何通过devtools实现热部署,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 详解基于IDEA2020.1的JAVA代码提示插件开发例子

    详解基于IDEA2020.1的JAVA代码提示插件开发例子

    这篇文章主要介绍了详解基于IDEA2020.1的JAVA代码提示插件开发例子,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • Java基础教程之String深度分析

    Java基础教程之String深度分析

    这篇文章主要给大家介绍了关于Java基础教程之String的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06

最新评论