栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JavaWeb项目基于SpringBoot框架实现统一的数据返回格式 + 统一异常处理 + 统一日志处理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaWeb项目基于SpringBoot框架实现统一的数据返回格式 + 统一异常处理 + 统一日志处理

目录

前言

统一返回格式

 添加枚举类

 添加统一返回格式的类

 测试

统一异常处理

 添加统一异常处理器(创建一个handler包,在该包下面添加GlobalExceptionHandler类)

测试统一异常处理

添加自定义异常类 (新建exception包,在该包下添加自定义异常类)

 在统一异常处理类GlobalExceptionHandler中添加一个自定义异常的处理

 测试自定义异常

统一日志处理

添加日志配置文件

添加application.properties配置

 修改GlobalExceptionHandler类

测试效果 

定义工具类(新建utils包,在该包下添加ExceptionUtils类) 

再修改GlobalExceptionHandler类

测试效果 

总结(源代码)


前言

大家好啊,我是爷爷的茶七里香,在我们的项目开发中,我们都会对数据返回格式进行统一的处理,这样可以方便前端人员取数据,当然除了正常流程的数据返回格式需要统一以外,我们也需要对异常的情况进行统一的处理,以及项目必备的日志这些,以下都会说明如何添加,写该文的目的是为了让新人了解在项目开发中,这些是咋做的。

统一返回格式

在项目开发中返回的是json格式的数据,也就是统一json数据返回格式,一般情况下返回数据的基本格式包含是否成功、响应状态码、返回的消息、以及返回的数据。格式如下: 

{
  "success": 布尔, 	   // 是否成功
  "code": 数字, 	   // 响应状态码
  "message": 字符串,   // 返回的消息
  "data": {}          //  放置响应的数据
}

下面开始实操:

  •  添加枚举类

该类定义了以上统一格式的前三部分:是否成功、响应状态码、返回的消息;可自行根据项目需要进行后续的添加或者删改。

创建一个result包,下面放置ResultCodeEnum枚举类

public enum ResultCodeEnum {

    SUCCESS(true, 20000, "成功"),

    UNKNOWN_REASON(false, 20001, "未知错误");

    private final Boolean success;

    private final Integer code;

    private final String message;

    ResultCodeEnum(Boolean success, Integer code, String message) {
        this.success = success;
        this.code = code;
        this.message = message;
    }

    public Boolean getSuccess() {
        return success;
    }

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        return "ResultCodeEnum{" + "success=" + success + ", code=" + code + ", message='" + message + ''' + '}';
    }
}
  •  添加统一返回格式的类

该类是用来和前端交互的类,定义的就是本文开头所说的格式

在result包下创建一个统一返回格式的类R

public class R {

    
    private Boolean success;

    
    private Integer code;

    
    private String message;

    
    private Map data = new HashMap<>();

    public R() {}

    
    
    public static R ok() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
        r.setCode(ResultCodeEnum.SUCCESS.getCode());
        r.setMessage(ResultCodeEnum.SUCCESS.getMessage());
        return r;
    }

    public static R error() {
        R r = new R();
        r.setSuccess(ResultCodeEnum.UNKNOWN_REASON.getSuccess());
        r.setCode(ResultCodeEnum.UNKNOWN_REASON.getCode());
        r.setMessage(ResultCodeEnum.UNKNOWN_REASON.getMessage());
        return r;
    }

    public static R setResult(ResultCodeEnum resultCodeEnum) {
        R r = new R();
        r.setSuccess(resultCodeEnum.getSuccess());
        r.setCode(resultCodeEnum.getCode());
        r.setMessage(resultCodeEnum.getMessage());
        return r;
    }

    public R success(Boolean success) {
        this.setSuccess(success);
        return this;
    }

    public R message(String message) {
        this.setMessage(message);
        return this;
    }

    public R code(Integer code) {
        this.setCode(code);
        return this;
    }

    public R data(String key, Object value) {
        this.data.put(key, value);
        return this;
    }

    public R data(Map map) {
        this.setData(map);
        return this;
    }

    

    public Boolean getSuccess() {
        return success;
    }

    public void setSuccess(Boolean success) {
        this.success = success;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public Map getData() {
        return data;
    }

    public void setData(Map data) {
        this.data = data;
    }
}
  •  测试

下面我们提供一个controller来测试下

@RestController
@RequestMapping("testR")
public class TestController {

    
    @GetMapping("ok")
    public R testOk() {
        Map data = new HashMap<>();
        data.put("name", "李太白");
        return R.ok().data(data);
    }
}

效果: 

可以看到格式是正确的,只要我们返回数据的时候使用R这个类返回就行了,不过有一种情况,就是当我们代码中抛出异常之后返回的格式就不是这样子了,下面我演示一下在代码中添加int a = 1/0的语句,肯定导致抛异常的;

 结果:

 可以发现返回的格式已经不是我们所需要的格式了,这种情况会给前端人员带来不必要的麻烦,所以我们也需要对异常情况进行统一的格式处理;

统一异常处理

 经过上面的演示,相信你已经明白我们为什么需要进行统一的异常处理了,当然处理统一的异常处理以外我们在开发项目中也会主动的抛出异常,像这种情况我们需要配合自定义异常来完成;

下面进行实操: 

  •  添加统一异常处理器(创建一个handler包,在该包下面添加GlobalExceptionHandler类)

@ControllerAdvice
public class GlobalExceptionHandler {

    
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error();
    }

}
  • 测试统一异常处理

可以看到现在出现异常之后返回的格式已经是我们所需要的格式了,如果我们想让这个错误信息更加明确,我们可以通过添加自定义异常来实现,下面开始实操:

  • 添加自定义异常类 (新建exception包,在该包下添加自定义异常类)

public class TestException extends RuntimeException {
    private Integer code;

    public TestException(ResultCodeEnum resultCodeEnum) {
        // 调用父类的方法添加信息
        super(resultCodeEnum.getMessage());
        this.code = resultCodeEnum.getCode();
    }

    public Integer getCode() {
        return code;
    }
}
  •  在统一异常处理类GlobalExceptionHandler中添加一个自定义异常的处理

@ControllerAdvice
public class GlobalExceptionHandler {

    
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error();
    }

    
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常
        e.printStackTrace();
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }

}
  •  测试自定义异常

在枚举类中添加一个状态信息

TEST_NUMBER(false, 500, "计算错误");

 输出结果:

现在自定义异常也能统一返回格式了

统一日志处理

为了更方便我们进行错误的调式,一般会在项目中集成日志,下面我们开始实操吧: 

  • 添加日志配置文件

在resources下添加日志的配置,文件名必须是logback-spring.xml 

以下配置一般不需要修改,要改的话也只是修改日志的输出目录

value就是日志的输出位置



    
    
    
    
    logback
    
    

    
    
    
    
    
    
    

    
    

    
    

    
    
        
            
            DEBUG
        
        
            
            ${CONSOLE_LOG_PATTERN}
            
            ${ENCODING}
        
    

    
    
        
        
            INFO
            ACCEPT
            DENY
        
        
        ${log.path}/log_info.log
        
            ${FILE_LOG_PATTERN}
            ${ENCODING}
        
        
        
            
            ${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log
            
                500MB
            
            
            15
        
    

    
        
        
            WARN
            ACCEPT
            DENY
        
        
        ${log.path}/log_warn.log
        
            ${FILE_LOG_PATTERN}
            ${ENCODING} 
        
        
        
            ${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log
            
                100MB
            
            
            15
        
    

    
        
        
            ERROR
            ACCEPT
            DENY
        
        
        ${log.path}/log_error.log
        
            ${FILE_LOG_PATTERN}
            ${ENCODING} 
        
        
        
            ${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log
            
                100MB
            
            
            15
        
    

    
    
        
        
            
            
            
            
        
    

    
    
        
            
        
    

  • 添加application.properties配置

 配置文件需要设置下环境,需要跟日志配置文件中的对应上,不然不生效

# 设置环境
spring.profiles.active=dev
  •  修改GlobalExceptionHandler类

具体修改看下面的代码:

@ControllerAdvice
public class GlobalExceptionHandler {

    
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常
        log.error(e.getMessage());
        // 返回错误格式信息
        return R.error();
    }

    
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常
        log.error(e.getMessage());
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }

}
  • 测试效果 

 日志生效了,而且在我们的D盘javaWeb目录下也有对应的日志文件了

 我们可以进一步的完善下,将日志堆栈信息输出到文件

  • 定义工具类(新建utils包,在该包下添加ExceptionUtils类) 

public class ExceptionUtils {
    public static String getMessage(Exception e) {
        StringWriter sw = null;
        PrintWriter pw = null;
        try {
            sw = new StringWriter();
            pw = new PrintWriter(sw);
            // 将出错的栈信息输出到printWriter中
            e.printStackTrace(pw);
            pw.flush();
            sw.flush();
        } finally {
            if (sw != null) {
                try {
                    sw.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
            if (pw != null) {
                pw.close();
            }
        }
        return sw.toString();
    }
}
  • 再修改GlobalExceptionHandler类

@ControllerAdvice
public class GlobalExceptionHandler {

    
    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    
    @ResponseBody
    @ExceptionHandler(Exception.class)
    public R exception(Exception e) {
        // 控制台打印异常  借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));
        // 返回错误格式信息
        return R.error();
    }

    
    @ResponseBody
    @ExceptionHandler(TestException.class)
    public R exception(TestException e) {
        // 控制台打印异常   借助工具类将错误堆栈输出到文件
        log.error(ExceptionUtils.getMessage(e));
        // 返回错误格式信息
        return R.error().message(e.getMessage()).code(e.getCode());
    }

}
  • 测试效果 

总结(源代码)

 到这就已经完成了统一返回格式、统一异常处理、已经统一的日志处理,通过文章不一定能看明白,所以我在此提供源代码,配合文章食用;

gitee仓库(本文章源代码)https://gitee.com/sgdygb/demo20220530

今天就到这里啦~对你有帮助的话不妨留个赞呗!

 磊原创不易,还希望各位大佬支持一下!

点赞,你的认可是我创作的动力 !

收藏,你的青睐是我努力的方向!

✏️评论,你的意见是我进步的财富!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/945443.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号