统一数据返回格式 及 可能遇到的问题;统一异常处理

简介: 统一数据返回格式需要创建一个新类并使其实现ResponseBodyAdvice 接口并重写里面的方法,然后给当前类加上@ControllerAdvice注解。实际应用时还有几个问题:问题一:重复打包问题二:ClassCastException: com.example.Spring_demo.Resp cannot be cast to java.lang.String统一异常处理需要使用两个注解@ExceptionHandler@ControllerAdvice

统一数据返回格式

统一数据返回格式就像我们寄快递一样,不管你需要寄的东西具体是什么都需要将它打包到统一的快递箱中。

此时我们需要一个“快递箱”用来将返回的数据“装”在里面。这个类是根据业务情况来自行定义的。

@Data
public class Resp<T> {
    //200-正常  0-发生异常
    private Integer code;
    //错误信息
    private String desc;
    //返回数据
    private T data;
    //成功
    public static <T> Resp<T> seccess(T data) {
        Resp<T> resp = new Resp<>();
        resp.setCode(200);
        resp.setData(data);
        return resp;
    }
}

image.gif

有了“快递箱之后”还需要一个“工作人员”来将“快递”进行打包,此时我们需要创建一个新类并使其实现ResponseBodyAdvice 接口并重写里面的方法,然后给当前类加上@ControllerAdvice注解。

@ControllerAdvice
public class Advice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return false;
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return null;
    }
}

image.gif

supports():这个方法用来决定是否执行beforeBodyWrite()方法,如果返回true表示执行,否则返回false。通过该方法可以选择哪些类或哪些方法的响应要进行处理,其他的不进行处理;beforeBodyWrite():对响应进行具体操作处理。

先创建两个用于测试的接口:

@RestController
@RequestMapping("/test")
public class Test {
    @RequestMapping("/fun1")
    public boolean fun1() {
        return false;
    }
    @RequestMapping("/fun2")
    public Integer fun2() {
        return 34;
    }
}

image.gif

image.gif

接下来将fun1和fun2方法的返回值进行“打包”。

@ControllerAdvice
public class Advice implements ResponseBodyAdvice {
    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        return Resp.seccess(body);
    }
}

image.gif

image.gif

但是实际应用时还有几个问题:

问题一:重复打包

如果此时fun1返回的就是Resp类型的值那么就会出现重复打包的问题。

@RequestMapping("/fun1")
public Resp<Boolean> fun1() {
    return Resp.seccess(false);
}

image.gif

image.gif

解决方法就是可以在打包前进行一次判断,如果已经被打包了就直接返回,否则进行打包。

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    if (body instanceof Resp) {
        return body;
    }
    return Resp.seccess(body);
}

image.gif

image.gif

问题二:ClassCastException: com.example.Spring_demo.Resp cannot be cast to java.lang.String

这个问题的出现场景是在返回值为String类型时出现的。假设fun1现在返回值是String类型:

@RequestMapping("/fun1")
public String fun1() {
    return "hahaha";
}

image.gif

image.gif

image.gif

解决方法就是如果返回结果为String类型, 使用SpringBoot内置提供的Jackson来实现信息的序列化。

@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    if (body instanceof String) {
        return new ObjectMapper().writeValueAsString(Resp.seccess(body));
    }
    if (body instanceof Resp) {
        return body;
    }
    return Resp.seccess(body);
}

image.gif

image.gif

注意:此时返回的是字符串。

使用这个就可以解决:@RequestMapping(value = "/fun1", produces = "application/json")

优点

  • 方便前端程序员更好的接收和解析后端数据接口返回的数据;
  • 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就可以了,因为所有接口都是这样返回的;
  • 有利于项目统一数据的维护和修改;
  • 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容。

统一异常处理

如果fun1方法在执行时出现异常也会出现不合理的返回信息:

@RequestMapping(value = "/fun1", produces = "application/json")
public String fun1() {
    System.out.println(3/0);
    return "hahaha";
}

image.gif

image.gif

此时就需要用到统一异常处理来对程序执行过程中发生的异常进行捕获和处理。统一异常处理需要使用两个注解@ExceptionHandler@ControllerAdvice,如果返回的是数据还需要加上@ResponseBody注解。

下面代码表示,如果代码出现Exception异常(包括Exception的子类)才会被捕获,然后执行该方法。

@ControllerAdvice
@ResponseBody
public class ErrorAdvice {
    @ExceptionHandler
    public Object handler(Exception e) {
        return Resp.fail("Exception: 程序出现异常");
    }
}

image.gif

image.gif

当有多个异常通知时,匹配顺序为当前类及其子类向上依次匹配。如此时有两个,继续访问fun1方法。

@ControllerAdvice
@ResponseBody
public class ErrorAdvice {
    @ExceptionHandler
    public Object handler(Exception e) {
        return Resp.fail("Exception: 程序出现异常");
    }
    @ExceptionHandler
    public Object handler(ArithmeticException e) {
        return Resp.fail("ArithmeticException: 程序出现算数异常");
    }
}

image.gif

image.gif

目录
相关文章
最新jsonwebtoken-jjwt 0.12.3 基本使用
最新jsonwebtoken-jjwt 0.12.3 基本使用
3727 1
|
JSON Java 应用服务中间件
HttpServletRequest核心方法以及获取请求参数
HttpServletRequest核心方法以及获取请求参数
2908 0
|
Oracle Java 关系型数据库
Oracle jdk 的国内下载镜像
Oracle jdk 的国内下载镜像
57739 0
|
前端开发 小程序 Java
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
本文详细介绍了如何在SpringBoot项目中统一处理接口返回结果及全局异常。首先,通过封装`ResponseResult`类,实现了接口返回结果的规范化,包括状态码、状态信息、返回信息和数据等字段,提供了多种成功和失败的返回方法。其次,利用`@RestControllerAdvice`和`@ExceptionHandler`注解配置全局异常处理,捕获并友好地处理各种异常信息。
7322 1
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
|
JSON Java API
jjwt使用说明-笔记
这篇文章介绍了如何使用jjwt库在Java中生成和验证JSON Web Tokens (JWT)。文章提供了在Maven项目中添加jjwt依赖的步骤,生成token的方法,以及如何验证token的示例代码。此外,还包含了一些关于token标准载荷和自定义载荷的说明,以及如何处理token验证过程中可能遇到的异常。
jjwt使用说明-笔记
|
Java 数据库连接 mybatis
成功解决: Invalid bound statement (not found) 在已经使用mybatis的项目里引入mybatis-plus,结果不能共存的解决
这篇文章讨论了在已使用MyBatis的项目中引入MyBatis-Plus后出现的"Invalid bound statement (not found)"错误,并提供了解决方法,主要是通过修改yml配置文件来解决MyBatis和MyBatis-Plus共存时的冲突问题。
成功解决: Invalid bound statement (not found) 在已经使用mybatis的项目里引入mybatis-plus,结果不能共存的解决
|
Java UED
基于SpringBoot自定义线程池实现多线程执行方法,以及多线程之间的协调和同步
这篇文章介绍了在SpringBoot项目中如何自定义线程池来实现多线程执行方法,并探讨了多线程之间的协调和同步问题,提供了相关的示例代码。
4520 0
|
算法 Nacos
Nacos遇到的无法下线问题,caused: errCode: 500, errMsg: do metadata operation failed ;caused: com.alibaba.naco
Nacos遇到的无法下线问题,caused: errCode: 500, errMsg: do metadata operation failed ;caused: com.alibaba.naco
|
负载均衡 网络协议 前端开发
一文快速上手 Nacos 注册中心+配置中心!
一文快速上手 Nacos 注册中心+配置中心!
9246 0
|
网络协议 Windows
【IntelliJ IDEA】idea plugins搜索不出来,如何找到插件的解决方案
【IntelliJ IDEA】idea plugins搜索不出来,如何找到插件的解决方案
13145 0

热门文章

最新文章