需求源自于任何一个业务的编写总会有各种各样的条件判断,需要时时手动抛出异常,又希望让接口返回友好的错误信息。

spring boot提供的帮助是自动将异常重定向到路由为/error的控制器

但是我们又希望手动抛出的异常与正常的数据返回为同一类型

所以我的解决方案由三个步骤组成:

1.一个异常枚举类 StatusCodeEnum.java

public enum StatusCodeEnum implements Serializable {
SUCCESS(0, "成功"),
ERROR(-1, "失败"),
USER_INVALID(60000, "无效用户"),
SYS_ARG_INVALID(11000, "无效参数"), ;
private static final long serialVersionUID = 1L;
private int code;
private String msg; StatusCodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} public String getMsg() {
return msg;
} public void setMsg(String msg) {
this.msg = msg;
} //根据code获取对应枚举
public static StatusCodeEnum getByCode(int code) {
StatusCodeEnum[] values = StatusCodeEnum.values(); for (StatusCodeEnum bizStatusCodeEnum : values) {
if (bizStatusCodeEnum.code == code) {
return bizStatusCodeEnum;
}
}
return null;
}
}

2.一个异常调用类 BaseException.java

因为抛出异常只能抛出字符串 所以这里使用了com.alibaba.fastjson.JSON包

public class BaseException {
private int code;
private String message; public static void error(StatusCodeEnum statusCodeEnum) throws Exception
{
error(statusCodeEnum.getCode(),statusCodeEnum.getMsg());
} public static void error(String message) throws Exception
{
error(-1,message);
} public static void error(int code,String message) throws Exception
{
BaseException baseException = new BaseException();
baseException.setCode(code);
baseException.setMessage(message);
throw new Exception(JSON.toJSONString(baseException)) ;
} public int getCode() {
return code;
} public void setCode(int code) {
this.code = code;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
} @Override
public String toString() {
return "BaseException{" +
"code=" + code +
", message='" + message + '\'' +
'}';
}
}

3.异常处理控制器 ErrorController.java

@Controller
public class ErrorController extends AbstractErrorController{ @Autowired
ObjectMapper objectMapper; public ErrorController() {
super(new DefaultErrorAttributes());
} @Override
public String getErrorPath() {
return null;
} @RequestMapping("/error")
@ResponseBody
public BaseRs getErrorPath(HttpServletRequest request, HttpServletResponse response) { Map<String,Object> model = Collections.unmodifiableMap(getErrorAttributes(request,false)); //获取异常 可将异常打印到日志
Throwable cause = getCause(request);
int status = (Integer)model.get("status"); //自定义友好错误信息
String msg = (String)model.get("message"); JSONObject object = JSONObject.parseObject(msg);
int code = object.getInteger("code");
String message = object.getString("message"); return new BaseRs(code,message);
} protected Throwable getCause(HttpServletRequest request)
{
Throwable error = (Throwable)request.getAttribute("javax.servlet.error.exception");
if(null == error){
//MVC有可能会封装异常成ServletException ,需要调用getCause获取真正的异常
while (error instanceof ServletException && error.getCause() != null){
error = ((ServletException) error).getCause();
}
}
return error;
}
}

以上三个文件为异常处理的核心

其中的BaseRs类是统一数据返回

public class BaseRs<T> implements Serializable {

    private int code;

    private String message;

    public BaseRs() {
} /**
* 返回内容
*/
private T content; public int getCode() {
return code;
} public String getMessage() {
return message;
} public T getContent() {
return content;
} public BaseRs(int code, String message) {
this.code = code;
this.message = message;
} public BaseRs(int code, String message, T content) {
this.code = code;
this.message = message;
this.content = content;
} public BaseRs(StatusCodeEnum status) {
this.code = status.getCode();
this.message = status.getMsg();
} public BaseRs(StatusCodeEnum status, T content) {
this.code = status.getCode();
this.message = status.getMsg();
this.content = content;
} public static <V> BaseRs ok(V content) {
return new BaseRs(StatusCodeEnum.SUCCESS, content);
} public static BaseRs ok() {
return new BaseRs(StatusCodeEnum.SUCCESS);
} public static BaseRs error(StatusCodeEnum error) {
return new BaseRs(error);
} public void setCode(StatusCodeEnum status) {
this.code = status.getCode();
} public void setMessage(String message) {
this.message = message;
} public void setContent(T content) {
this.content = content;
} @Override
public String toString() {
return "BaseRs{" +
"code=" + code +
", message='" + message + '\'' +
", content=" + content +
'}';
} public void setCode(int code) {
this.code = code;
}
}

最后的控制层代码以最简洁的方式调用即可:

@Controller
public class IndexController {
@RequestMapping("/a")
@ResponseBody
public BaseRs a() throws Exception{
boolean s = false;
if(!s){
BaseException.error(StatusCodeEnum.USER_INVALID);
}
return new BaseRs(StatusCodeEnum.SUCCESS);
}
}

本篇博客的码云地址: https://gitee.com/zhao-baolin/springboot_error

spring boot 统一异常处理的更多相关文章

  1. Spring Boot统一异常处理实践

    摘要: SpringBoot异常处理. 原文:Spring MVC/Boot 统一异常处理最佳实践 作者:赵俊 前言 在 Web 开发中, 我们经常会需要处理各种异常, 这是一件棘手的事情, 对于很多 ...

  2. Spring Boot☞ 统一异常处理

    效果区:  代码区: package com.wls.integrateplugs.exception.dto; public class ErrorInfo<T> { public st ...

  3. Spring Boot统一异常处理方案示例

    一.异常处理的原则 1.调用方法的时候返回布尔值来代替返回null,这样可以 NullPointerException.由于空指针是java异常里最恶心的异常. 2. catch块里别不写代码.空ca ...

  4. Spring MVC 统一异常处理

    Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或 ...

  5. 编程小白入门分享三:Spring AOP统一异常处理

    Spring AOP统一异常处理 简介 在Controller层,Service层,可能会有很多的try catch代码块.这将会严重影响代码的可读性."美观性".怎样才可以把更多 ...

  6. Spring Boot全局异常处理

    本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下 1.后台处理异常 a.引入thymeleaf依赖 <!-- thymeleaf模板插件 --> <dep ...

  7. Spring Boot 统一返回结果及异常处理

    在 Spring Boot 构建电商基础秒杀项目 (三) 通用的返回对象 & 异常处理 基础上优化.调整 一.通用类 1.1 通用的返回对象 public class CommonReturn ...

  8. spring boot 统一接口异常返回值

    创建业务 Exception 一般在实际项目中,推荐创建自己的 Exception 类型,这样在后期会更容易处理,也比较方便统一,否则,可能每个人都抛出自己喜欢的异常类型,而造成代码混乱 Servic ...

  9. 使用Spring MVC统一异常处理实战

    1 描述 在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的.不可预知的异常需要处理.每个过程都单独处理异常,系统的代码耦合 ...

随机推荐

  1. js中常用的正则表达式总结

    去除所有空格: str = str.replace(/\s+/g,""); 去除两头空格: str = str.replace(/^\s+|\s+$/g,"") ...

  2. C++第四课:类的使用(二)[个人见解]

    前面说到C++类的名字自定义要有含义,成员函数名也同样如此. 一个好的程序员除了让自己能看懂代码外,那是能力,也能让别人看懂,那是本事. 我们来看第一个特性:继承! 什么是继承? 小编不说概念性的定义 ...

  3. window下如何使用文本编辑器(如记事本)创建、编译和执行Java程序

    window下如何使用文本编辑器(如记事本)创建Java源代码文件,并编译执行 第一步:在一个英文目录下创建一个 .text 文件 第二步:编写代码 第三步:保存文件 方法一:选择 文件>另存为 ...

  4. 把.zip文件转化为.tar.gz文件

    工作中正好用到上传tar.gz文件,没有现成的转换工具,就写了方法转换 #encoding: utf-8import osimport tarfileimport zipfileimport osim ...

  5. MySQL5.6启用sha256_password插件

    一.背景: 使用MySQL5.6过程中,发现默认的加密插件为mysql_native_password.而sha256_password的安全程度要比mysql_native_password高,尝试 ...

  6. Android系统架构及内核简介

    (来源于ThinkPHP) Android是Google公司开发的基于Linux平台的开源手机操作系统,它包括操作系统.中间件.用户界面和应用程序,而且不存在任何以往阻碍移 动产业创新的专利权障碍,并 ...

  7. Spring + SpringMVC + Mybatis项目中redis的配置及使用

    maven文件 <!-- redis --> <dependency> <groupId>redis.clients</groupId> <art ...

  8. sql_update

    学习: http://www.runoob.com/mysql/mysql-tutorial.html replace: update table_name set column = replace ...

  9. 03-es6语法 Promise 和 es8语法 async await 的了解和基本使用

    //Promise // 1.说明 : Promise 是 es6 中提出的新语法 // 2.作用 : 用 '用户编写同步代码' 的方式 '处理异步' 的一种解决方案 // 3.以前 : 处理异步 , ...

  10. 《JavaScript DOM编程艺术》学习笔记(三)

    终于要完成这最后一部分了,距离第二部分已经过去五天了,一直想早点写的,但还是拖到今天了………… 34.position属性的和法制:static是position属性的默认值,意思是有关元素将按照它们 ...