• springboot全局异常处理详解


    对于全局异常需要认识两个注解
    @RestControllerAdvice,@ExceptionHandler

    1、 @RestControllerAdvice

    • 在这里插入图片描述

    组成:@ControllerAdvice、@ResponseBody

    @RestControllerAdvice特点:
    (1)通过@ControllerAdvice注解可以将对于控制器的全局配置放在同一个位置,他可以管理所有的Controller。
    (2)注解了@RestControllerAdvice的类的方法可以使用@ExceptionHandler、@InitBinder、@ModelAttribute注解到方法上。
    (3)@RestControllerAdvice注解将作用在所有注解了@RequestMapping的控制器的方法上。
    (4)@ExceptionHandler:用于指定异常处理方法。当与@RestControllerAdvice配合使用时,用于全局处理控制器里的异常。
    (5)

    • @InitBinder:用来设置WebDataBinder,用于自动绑定前台请求参数到Model中。

    • @ModelAttribute:本来作用是绑定键值对到Model中,当与@ControllerAdvice配合使用时,可以让全局的@RequestMapping都能获得在此处设置的键值对**

    2、@ExceptionHandler注解我们一般是用来自定义异常的。
    可以认为它是一个异常拦截器(处理器)。

    @ExceptionHandler(xxx.class)

    在这里插入图片描述xxx.class是具体的异常类
    例如:NullPointerException
    在这里插入图片描述
    例子

    全局异常捕获
    在这里插入图片描述
    自定义异常类
    在这里插入图片描述
    自定义异常类继承RuntimeException

    public class Mall4cloudException extends RuntimeException {
    
    	private static final long serialVersionUID = 1L;
    
    	private Object object;
    
    	private ResponseEnum responseEnum;
    
    	public Mall4cloudException(String msg) {
    		super(msg);
    	}
    
    	public Mall4cloudException(String msg, Object object) {
    		super(msg);
    		this.object = object;
    	}
    
    	public Mall4cloudException(String msg, Throwable cause) {
    		super(msg, cause);
    	}
    
    
    	public Mall4cloudException(ResponseEnum responseEnum) {
    		super(responseEnum.getMsg());
    		this.responseEnum = responseEnum;
    	}
    
    	public Mall4cloudException(ResponseEnum responseEnum, Object object) {
    		super(responseEnum.getMsg());
    		this.responseEnum = responseEnum;
    		this.object = object;
    	}
    
    
    	public Object getObject() {
    		return object;
    	}
    
    	public ResponseEnum getResponseEnum() {
    		return responseEnum;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    自定义返回状态码类型

    package com.mall4j.cloud.common.response;
    
    /**
     * @author FrozenWatermelon
     * @date 2020/7/9
     */
    public enum ResponseEnum {
    
    	/**
    	 * ok
    	 */
    	OK("00000", "ok"),
    
    	/**
    	 * 用于直接显示提示用户的错误,内容由输入内容决定
    	 */
    	SHOW_FAIL("A00001", ""),
    
    	/**
    	 * 方法参数没有校验,内容由输入内容决定
    	 */
    	METHOD_ARGUMENT_NOT_VALID("A00002", ""),
    
    	/**
    	 * 无法读取获取请求参数
    	 */
    	HTTP_MESSAGE_NOT_READABLE("A00003", "请求参数格式有误"),
    
    	/**
    	 * 未授权
    	 */
    	UNAUTHORIZED("A00004", "Unauthorized"),
    
    	/**
    	 * 服务器出了点小差
    	 */
    	EXCEPTION("A00005", "服务器出了点小差"),
    
    	/**
    	 * 数据异常
    	 */
    	DATA_ERROR("A00007", "数据异常,请刷新后重新操作"),
    
    	/**
    	 * 一些需要登录的接口,而实际上因为前端无法知道token是否已过期,导致token已失效时,
    	 * 应该返回一个状态码,告诉前端token已经失效了,及时清理
    	 */
    	CLEAN_TOKEN("A00008", "clean token"),
    
    	/**
    	 * 刷新token已过期
    	 */
    	REFRESH_TOKEN_EXIST("A00009", "refresh token exist"),
    
    	/**
    	 * 数据不完整
    	 */
    	DATA_INCOMPLETE("A00010", "数据不完整"),
    
    	/**
    	 * 01开头代表商品
    	 */
    	SPU_NOT_EXIST("A01000", "spu not exist"),
    
    	/**
    	 * 02开头代表购物车
    	 */
    	SHOP_CART_NOT_EXIST("A02000", "shop cart not exist"),
    
    	/**
    	 * 03开头代表订单
    	 */
    	ORDER_NOT_EXIST("A03000", "order not exist"),
    
    	/**
    	 * 请勿重复提交订单,
    	 * 1.当前端遇到该异常时,说明前端防多次点击没做好
    	 * 2.提示用户 订单已发生改变,请勿重复下单
    	 */
    	REPEAT_ORDER("A03002", "please don't repeat order"),
    
    	/**
    	 * 订单已过期,当前端看到该状态码的时候,提示订单信息已过期,请重新确认后提交,此时用户点击确定,前端刷新页面。
    	 */
    	ORDER_EXPIRED("A03003", "order expired"),
    
    	/**
    	 * 订单已支付,无法取消订单
    	 */
    	ORDER_PAYED("A03007", "order payed"),
    
    	/**
    	 * 订单未发货,无法确认收货
    	 */
    	ORDER_NO_DELIVERY("A03008", "order no delivery"),
    
    	/**
    	 * 库存不足,body会具体返回那个skuid的库存不足
    	 */
    	NOT_STOCK("A03010", "not stock"),
    
    	/**
    	 * 订单未完成或未关闭,无法删除订单
    	 */
    	ORDER_NOT_FINISH_OR_CLOSE("A03011", "order not finish or close"),
    
    	/**
    	 * 订单未支付
    	 */
    	ORDER_NOT_PAYED("A03012", "order not payed"),
    
    	/**
    	 * 订单已失败
    	 */
    	ORDER_HAS_FAILED("A03013", "order has failed"),
    
    	/**
    	 * 没有查询权限
    	 */
    	REFUND_NOT_PERMISSION("A03024", "refund not permission"),
    
    	/**
    	 * 撤销失败 当前状态不允许此操作
    	 */
    	REFUND_STATUS_CHECK("A03034", "refund status check"),
    
    	/**
    	 * 04 开头代表注册登录之类的异常状态
    	 * 社交账号未绑定,当前端看到该异常时,应该在合适的时间(比如在购买的时候跳)根据社交账号的类型,跳转到绑定系统账号的页面
    	 */
    	SOCIAL_ACCOUNT_NOT_BIND("A04001", "social account not bind"),
    
    	/**
    	 * 有些时候第三方系统授权之后,会有个临时的key,比如小程序的session_key
    	 * 这个异常代表session_key过期,前端遇到这个问题的时候,应该再次调用社交登录的接口,刷新session_key
    	 */
    	BIZ_TEMP_SESSION_KEY_EXPIRE("A04002", "biz temp session key expire"),
    
    	/**
    	 * 账号未注册,前端看到这个状态码,弹出选择框,提示用户账号未注册,是否进入注册页面,用户选择是,进入注册页面
    	 */
    	ACCOUNT_NOT_REGISTER("A04003", "account not register");
        private final String code;
    
    	private final String msg;
    
    	public String value() {
    		return code;
    	}
    
    	public String getMsg() {
    		return msg;
    	}
    
    	ResponseEnum(String code, String msg) {
    		this.code = code;
    		this.msg = msg;
    	}
    
    	@Override
    	public String toString() {
    		return "ResponseEnum{" + "code='" + code + ''' + ", msg='" + msg + ''' + "} " + super.toString();
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165

    这个是返回状态码的初始化,就是每个接口都会返回状态码的格式

    package com.mall4j.cloud.common.response;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.Serializable;
    import java.util.Objects;
    
    /**
     * 统一的返回数据
     *
     * @author FrozenWatermelon
     * @date 2020/7/3
     */
    public class ServerResponseEntity implements Serializable {
    
    	private static final Logger log = LoggerFactory.getLogger(ServerResponseEntity.class);
    
    	/**
    	 * 状态码
    	 */
    	private String code;
    
    	/**
    	 * 信息
    	 */
    	private String msg;
    
    	/**
    	 * 数据
    	 */
    	private T data;
    
    	public String getCode() {
    		return code;
    	}
    
    	public void setCode(String code) {
    		this.code = code;
    	}
    
    	public String getMsg() {
    		return msg;
    	}
    
    	public void setMsg(String msg) {
    		this.msg = msg;
    	}
    
    	public T getData() {
    		return data;
    	}
    
    	public void setData(T data) {
    		this.data = data;
    	}
    
    	public boolean isSuccess() {
    		return Objects.equals(ResponseEnum.OK.value(), this.code);
    	}
    
    	@Override
    	public String toString() {
    		return "ServerResponseEntity{" + "code=" + code + ", msg='" + msg + ''' + ", data=" + data + '}';
    	}
    
    	public static  ServerResponseEntity success(T data) {
    		ServerResponseEntity serverResponseEntity = new ServerResponseEntity<>();
    		serverResponseEntity.setData(data);
    		serverResponseEntity.setCode(ResponseEnum.OK.value());
    		return serverResponseEntity;
    	}
    
    	public static  ServerResponseEntity success() {
    		ServerResponseEntity serverResponseEntity = new ServerResponseEntity<>();
    		serverResponseEntity.setCode(ResponseEnum.OK.value());
    		serverResponseEntity.setMsg(ResponseEnum.OK.getMsg());
    		return serverResponseEntity;
    	}
    
    	/**
    	 * 前端显示失败消息
    	 * @param msg 失败消息
    	 * @return
    	 */
    	public static  ServerResponseEntity showFailMsg(String msg) {
    		log.error(msg);
    		ServerResponseEntity serverResponseEntity = new ServerResponseEntity<>();
    		serverResponseEntity.setMsg(msg);
    		serverResponseEntity.setCode(ResponseEnum.SHOW_FAIL.value());
    		return serverResponseEntity;
    	}
    
    	public static  ServerResponseEntity fail(ResponseEnum responseEnum) {
    		log.error(responseEnum.toString());
    		ServerResponseEntity serverResponseEntity = new ServerResponseEntity<>();
    		serverResponseEntity.setMsg(responseEnum.getMsg());
    		serverResponseEntity.setCode(responseEnum.value());
    		return serverResponseEntity;
    	}
    
    	public static  ServerResponseEntity fail(ResponseEnum responseEnum, T data) {
    		log.error(responseEnum.toString());
    		ServerResponseEntity serverResponseEntity = new ServerResponseEntity<>();
    		serverResponseEntity.setMsg(responseEnum.getMsg());
    		serverResponseEntity.setCode(responseEnum.value());
    		serverResponseEntity.setData(data);
    		return serverResponseEntity;
    	}
    
    	public static  ServerResponseEntity transform(ServerResponseEntity oldServerResponseEntity) {
    		ServerResponseEntity serverResponseEntity = new ServerResponseEntity<>();
    		serverResponseEntity.setMsg(oldServerResponseEntity.getMsg());
    		serverResponseEntity.setCode(oldServerResponseEntity.getCode());
    		log.error(serverResponseEntity.toString());
    		return serverResponseEntity;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119

    接口层会返回固定的格式
    在这里插入图片描述
    后续更新自定义异常处理

    码云地址:https://gitee.com/yuisuiWork/spring_project_demo/
    欢迎交流,一起进步!

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    高阶数据结构:并查集
    美摄AR人像美颜,全新视觉体验
    python学习15--数据分析(matplotlib、numpy)
    Java笔记 实用类(二)
    【容器网络】跨主通信网络实现方法之UDP实现原理
    线性代数-矩阵的逆
    独一无二:探索单例模式的现代化创造之道
    JavaScript学习——什么是编程语言?计算机基础
    rosbag保存 pcd和image
    vivado 时序约束
  • 原文地址:https://blog.csdn.net/m0_67401153/article/details/126114444