欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-22 11:05:44
目录@restcontrolleradvice与@controlleradvice的区别@controlleradvice注解的源码为@restcontrolleradvice注解的源码为@restc...

@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());
    }
}

最后拦截效果图如下:

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

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