springboot 详解RestControllerAdvice(ControllerAdvice)(转)
springboot 详解RestControllerAdvice(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 {};
}
作为特化@Component,允许通过类路径扫描自动检测实现类。
它通常用于定义@ExceptionHandler, @InitBinder 和 @ModelAttribute 适用于所有@RequestMapping方法的方法。
annotations(),basePackageClasses(), basePackages()或它的别名value() 可以被指定,以限定控制器,以协助的特定子集。当应用多个选择器时,应用OR逻辑 - 意味着所选的控制器应匹配至少一个选择器。
默认行为(即,如果没有任何选择器使用),带@ControllerAdvice注释的类将协助所有已知的控制器。
背景
当我们定义了一个自定义返回参数格式时,希望得到统一的返回,如果在运行时发现了异常,也希望将异常统一返回。如
期望返回格式:
{
"msg": "success",
"code": 500,
"success": false,
"message": "id不能为空!"
}
抛出异常格式:
{
"timestamp": "2019-04-01T07:17:38.619+0000",
"status": 500,
"error": "Internal Server Error",
"message": "id不能为空!",
"path": "/api/myInfo"
}
如何让我们的异常得到期望的返回格式,这里就需要用到了@ControllerAdvice或者RestControllerAdvice(如果全部异常处理返回json,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,这样在方法上就可以不需要添加 @ResponseBody。)。下面看一个demo。
准备工作
1.创建一个UnionExceptionHandler类,定义全局异常捕捉处理。
package com.honghh.bootfirst.exception; import com.honghh.bootfirst.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestControllerAdvice; /**
* ClassName: UnionExceptionHandler
* Description:
*
* @author honghh
* @date 2019/04/01 10:03
*/
@Slf4j
@RestControllerAdvice
public class UnionExceptionHandler { /**
* 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
*
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
log.info("binder.getFieldDefaultPrefix {}",binder.getFieldDefaultPrefix());
log.info("binder.getFieldMarkerPrefix {}",binder.getFieldMarkerPrefix());
}
/**
* 把值绑定到Model中,使全局@RequestMapping可以获取到该值
* @param model
*/
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("author", "harry");
}
/**
* Description : 全局异常捕捉处理
* Group :
*
* @author honghh
* @date 2019/4/1 0001 10:34
* @param ex
* @return
*/
@ExceptionHandler(RRException.class)
public R apiExceptionHandler(RRException ex) {
log.error("ApiException 异常抛出:{}", ex);
return R.fail(ex);
}
/**
* Description : 针对某个异常捕捉处理
* Group :
*
* @author honghh
* @date 2019/4/1 0001 10:34
* @param ex
* @return
*/
@ExceptionHandler(SSException.class)
public R apiExceptionHandler(SSException ex) {
log.error("ApiException 异常抛出:{}", ex);
return R.fail(ex);
}
}
启动应用后,被 @ExceptionHandler、@InitBinder、@ModelAttribute 注解的方法,都会作用在 @RequestMapping 注解的方法上。
@ModelAttribute:在Model上设置的值,对于所有被 @RequestMapping 注解的方法中,都可以通过 ModelMap 获取
2.创建一个RRException 自定义异常。
package com.honghh.bootfirst.exception;
/**
* 自定义异常
*
* @author harry
* @date 2018-07-20 16:30
*/
public class RRException extends RuntimeException {
private static final long serialVersionUID = 1L; private String msg;
private int code = 500; public RRException(String msg) {
super(msg);
this.msg = msg;
} public RRException(String msg, Throwable e) {
super(msg, e);
this.msg = msg;
} public RRException(String msg, int code) {
super(msg);
this.msg = msg;
this.code = code;
} public RRException(String msg, int code, Throwable e) {
super(msg, e);
this.msg = msg;
this.code = code;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} }
3.写一个RequestMapping方法,抛出异常进行测试。[spring boot 默认情况下会映射到 /error 进行异常处理,但是提示并不十分友好,下面自定义异常处理,提供友好展示。
@GetMapping("myInfo")
public R myInfo(@RequestParam Integer id) {
if (id == null) {
throw new RRException("id不能为空!");
}
MyInfo myInfo = myInfoService.getById(id);
return R.ok().put("myInfo", myInfo);
}
//启动应用,访问:http://127.0.0.1:8080/api/myInfo?id= ,正常显示以下json内容,证明自定义异常已经成功被拦截。
{
"msg": "success",
"code": 500,
"success": false,
"message": "id不能为空!"
}
代码获取
https://gitee.com/honghh/boot-demo.git
参考文献
https://docs.spring.io/spring-framework/docs/5.0.0.M1/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html
————————————————
版权声明:本文为CSDN博主「AH_HH」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_35098526/article/details/88949425
springboot 详解RestControllerAdvice(ControllerAdvice)(转)的更多相关文章
- SpringBoot详解
1.Hello,World! 1.1.SpringBoot简介 回顾什么是Spring Spring是一个开源框架,2003 年兴起的一个轻量级的Java 开发框架,作者:Rod Johnson . ...
- SpringBoot详解(一)——
https://www.cnblogs.com/lifullmoon/p/14957771.html https://www.cnblogs.com/lifullmoon/p/14957751.htm ...
- SPRINGBOOT注解最全详解(
# SPRINGBOOT注解最全详解(整合超详细版本) 使用注解的优势: 1.采用纯java代码,不在需要配置繁杂的xml文件 ...
- Springboot 整合 Dubbo/ZooKeeper 详解 SOA 案例
摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “看看星空,会觉得自己很渺小,可能我们在宇宙中从来就是一个偶然.所以,无论什么事情,仔细想一 ...
- Springboot启动源码详解
我们开发任何一个Spring Boot项目,都会用到如下的启动类 @SpringBootApplication public class Application { public static voi ...
- springboot配置详解
springboot配置详解 Author:SimpleWu properteis文件属性参考大全 springboot默认加载配置 SpringBoot使用两种全局的配置文件,全局配置文件可以对一些 ...
- spring-boot(五) RabbitMQ详解 定时任务
学习文章来自:springboot(八):RabbitMQ详解 springboot(九):定时任务 RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分 ...
- Springboot@Configuration和@Bean详解
Springboot@Configuration和@Bean详解 一.@Configuration @Target({ElementType.TYPE}) @Retention(RetentionPo ...
- [转]application.properties详解 --springBoot配置文件
本文转载:http://blog.csdn.net/lpfsuperman/article/details/78287265###; # spring boot application.propert ...
随机推荐
- poj1915(双向bfs)
题目链接:https://vjudge.net/problem/POJ-1915 题意:求棋盘上起点到终点最少的步数. 思路:双向广搜模板题,但玄学的是我的代码G++会wa,C++过了,没找到原因QA ...
- c# 金钱大写转小写工具类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 洛谷 P4198 楼房重建 线段树维护单调栈
P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...
- __formart__
__format__ 一.__format__ 自定制格式化字符串 date_dic = { 'ymd': '{0.year}:{0.month}:{0.day}', 'dmy': '{0.day}/ ...
- 【背包问题】PACKING
题目描述 It was bound to happen. Modernisation has reached the North Pole. Faced with escalating costs ...
- .Net C# RSA签名和验签
帮助类 using System; using System.Text; using System.IO; using System.Security.Cryptography; namespace ...
- 使用NPOI导出Excel文件
使用NPOI导出Excel文件,本实例使用了ASP.NET MVC. 1.使用NPOI导出Excel文件 实例:导出商品列表. 要求:1.通过NPOI导出导出商品列表信息: 2.使用Excel函数计算 ...
- 安装 node.js npm,cnpm
参考:https://blog.csdn.net/suiyuehuimou/article/details/74143436 https://www.liaoxuefeng.com/wiki/0014 ...
- JavaScript Basics_Fundamentals Part 2_A simple calendar
下方的日历框架是从 Active learning: A simple calendar 上整过来的. 主要任务是用 if...else 语句来让日历本显示出每月相对应的天数,相关代码已经给出,我们只 ...
- vue cli创建脚手架
1.用vscode打开一个文件夹.在菜单栏 点击 查看-集成终端.这里可以用其他的方法比如cmd命令符调开这个界面,但是要用cd 切到要放文件的文件夹下. 2.安装好node.js 和淘宝镜像 3. ...