基于@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()); } }
最后拦截效果图如下:
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。
推荐阅读
-
基于Python __dict__与dir()的区别详解
-
基于Linux下Nagios的安装与配置说明介绍[图]
-
php 转换字符串编码 iconv与mb_convert_encoding的区别说明
-
CSS伪类与CSS伪元素的区别及由来具体说明
-
基于session_unset与session_destroy的区别详解
-
PHP中基于ts与nts版本- vc6和vc9编译版本的区别详解
-
通过5个php实例细致说明传值与传引用的区别
-
基于magic_quotes_gpc与magic_quotes_runtime的区别与使用介绍
-
基于numpy.random.randn()与rand()的区别详解
-
asp中的rs.open与conn.execute的区别说明