springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)
一.引入相应的maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二.自定义参数校验注解
/**
* @Author: guandezhi
* @Date: 2019/3/11 13:07
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ParamValidate {
String value() default "";
}
三.自定义异常切面
package com.gdz.paramvalidate.aspect; import com.gdz.paramvalidate.annotation.ParamValidate;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError; import java.lang.reflect.Method;
import java.util.List; /**
* 异常处理切面
* @Author: guandezhi
* @Date: 2019/3/11 13:03
*/
@Slf4j
@Aspect
@Component
public class ExceptionAspect { @Before("@annotation(com.gdz.paramvalidate.annotation.ParamValidate)")
public void before(JoinPoint jp) throws Exception {
doBefore(jp);
} private void doBefore(JoinPoint jp) throws Exception {
if (getParamValidate(jp) == null) {return;}
Object[] args = jp.getArgs();
if (args == null) {return;}
//将异常格式化成通用格式
formateException(args);
} private ParamValidate getParamValidate(JoinPoint jp) {
MethodSignature methodSignature = (MethodSignature) jp.getSignature();
Method method = methodSignature.getMethod();
return method.getAnnotation(ParamValidate.class);
} private void formateException(Object[] args) throws Exception {
for (Object arg : args) {
if (arg instanceof BindingResult) {
BindingResult result = (BindingResult) arg;
if (result != null && result.getErrorCount() > 0) {
List<ObjectError> errors = result.getAllErrors();
String errorMsg = "";
for (ObjectError error : errors) {
if (error instanceof FieldError) {
FieldError fe = (FieldError) error;
errorMsg = String.format("%s:%s", fe.getField(), error.getDefaultMessage());
} else {
errorMsg = String.format("%s:%s ", error.getCode(), error.getDefaultMessage());
}
log.error(errorMsg);
throw new Exception(errorMsg);
}
}
}
}
} }
四.自定义全局异常处理器
package com.gdz.paramvalidate.exception; import com.gdz.paramvalidate.bean.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; /**
* 全局异常处理
*
* @Author: guandezhi
* @Date: 2019/3/11 14:43
*/
@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler { @ResponseBody
@ExceptionHandler(value = Exception.class)
public ResultVo<Object> handleException(Exception e) {
String errorMsg = "";
if (e instanceof NullPointerException) {
errorMsg = "参数空指针异常";
} else if (e instanceof HttpMessageNotReadableException) {
errorMsg = "请求参数匹配错误," + e.getLocalizedMessage();
} else {
errorMsg = e.getMessage();
}
log.error(String.format("请求异常[%s]", e)); ResultVo<Object> resultVo = new ResultVo<>();
resultVo.setResultCode("501");
resultVo.setResultMsg(errorMsg);
return resultVo;
}
}
其中的resultVo如下: /**
* @Author: guandezhi
* @Date: 2019/3/11 12:14
*/
@Data
public class ResultVo<T> { private String resultCode; private String resultMsg; private T data; }
五.在需要校验入参的controller方法上加上自定义注(@ParamValidate)
/**
* @Author: guandezhi
* @Date: 2019/3/11 12:15
*/
@Slf4j
@RequestMapping("/user")
@RestController
public class UserController { @ParamValidate
@RequestMapping("/addUser")
public String addUser(@RequestBody @Valid User user, BindingResult result) throws Exception {
int i = 1 / 0;
return "success";
}
}
这里必须加上@ParamValidate @Valid这两个注解才能生效
其中User类如下:
/**
* @Author: guandezhi
* @Date: 2019/3/11 12:19
*/
@Data
public class User { @NotNull(message = "用户名不能为空")
private String name; @NotNull(message = "手机号不能为空")
private String mobile;
}
六.测试一下
1.当入参为空值时

1.当程序有异常时

代码地址:https://github.com/dezhiguan/GlobalExceptionHandler
---------------------
作者: guandezhi
来源:CSDN
原文:https://blog.csdn.net/qq_35859844/article/details/88394376
版权声明:本文为博主原创文章,转载请附上博文链接!
springboot+aop+自定义注解,打造通用的全局异常处理和参数校验切面(通用版)的更多相关文章
- 全局异常处理及参数校验-SpringBoot 2.7 实战基础 (建议收藏)
优雅哥 SpringBoot 2.7 实战基础 - 08 - 全局异常处理及参数校验 前后端分离开发非常普遍,后端处理业务,为前端提供接口.服务中总会出现很多运行时异常和业务异常,本文主要讲解在 Sp ...
- springboot aop 自定义注解方式实现完善日志记录(完整源码)
版权声明:本文为博主原创文章,欢迎转载,转载请注明作者.原文超链接 一:功能简介 本文主要记录如何使用aop切面的方式来实现日志记录功能. 主要记录的信息有: 操作人,方法名,参数,运行时间,操作类型 ...
- springboot aop 自定义注解方式实现一套完善的日志记录(完整源码)
https://www.cnblogs.com/wenjunwei/p/9639909.html https://blog.csdn.net/tyrant_800/article/details/78 ...
- springboot aop 自定义注解
枚举类: /** * Created by tzq on 2018/5/21. */ public enum MyAnnoEnum { SELECT("select"," ...
- 使用AOP+自定义注解完成spring boot的接口权限校验
记使用AOP+自定义注解完成接口的权限校验,代码如下: pom文件添加所需依赖: 1 <dependency> 2 <groupId>org.aspectj</group ...
- SpringBoot系列(十三)统一日志处理,logback+slf4j AOP+自定义注解,走起!
往期精彩推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配置文件详解 SpringBoot系列(四)we ...
- redis分布式锁-spring boot aop+自定义注解实现分布式锁
接这这一篇redis分布式锁-java实现末尾,实现aop+自定义注解 实现分布式锁 1.为什么需要 声明式的分布式锁 编程式分布式锁每次实现都要单独实现,但业务量大功能复杂时,使用编程式分布式锁无疑 ...
- 利用Spring AOP自定义注解解决日志和签名校验
转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先 ...
- ssm+redis整合(通过aop自定义注解方式)
此方案借助aop自定义注解来创建redis缓存机制. 1.创建自定义注解类 package com.tp.soft.common.util; import java.lang.annotation.E ...
随机推荐
- session+验证码 学习
分析 LoginServlet类 @WebServlet("/loginServlet") public class LoginServlet extends HttpServle ...
- java实现spark常用算子之groupbykey
import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaPairRDD;import org.apache.spa ...
- JavaScript快速排序法实现数组排序
大致分三步: 1.找基准(一般是以中间项为基准) 2.遍历数组,小于基准的放在left,大于基准的放在right 3.递归 var arr = [10,8,6,9,1,7,1,13,5,1,9]; / ...
- PHP高级进阶之路
一:常见模式与框架 学习PHP技术体系,设计模式,流行的框架 常见的设计模式,编码必备 Laravel.ThinkPHP开发必不可少的最新框架 YII.Symfony4.1核心源码剖析 二:微服务架构 ...
- ccs之经典布局(一)(水平垂直居中)
经典的css布局有以下几种,下面分别用不同的方法进行实现且进行对比. 一.水平居中 水平居中布局指的是当前元素在父级元素的容器中,水平方向上显示的是居中的,有以下几种方式来完成布局: 1.margin ...
- ECharts模拟百度迁徙实例
本实例原始信息: 作者:anix 演示地址:Echarts模拟迁徙 源码地址:GitHub-ananix-qianxi 前言 "百度地图春节人口迁徙大数据"(简称"百度迁 ...
- 使输入框(input & textarea)变为只可读状态readonly="readonly",禁用输入框disabled="disabled"
使输入框变为只可读状态 readonly="readonly" <input class="select-city" placeholder=" ...
- Spark查询yarn任务日志
查看日志:yarn logs -applicationId application_xxx 导入到外部文件 yarn logs -applicationId application_xxx >& ...
- python的isocalender()
isocalender()返回指定日期的年,第几周,周几这三个值. 例子: import date date_time = datetime.date(2019, 5, 9) ret = date_t ...
- zabbix监控,微信报警
微信告警 访问这个地址创建企业微信 https://work.weixin.qq.com/