全局统一返回RESTful风格数据,主要是实现ResponseBodyAdvice接口的方法,对返回值在输出之前进行修改。
使用注解@RestControllerAdvice拦截异常并统一处理。

开发环境:
IntelliJ IDEA 2019.2.2
jdk1.8
Spring Boot 2.2.2

1、创建一个SpringBoot项目,pom.xml引用的依赖包如下

        <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>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>

2、定义一个返回类

package com.example.response.entity;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString; import java.io.Serializable; @Data
@NoArgsConstructor
@ToString
public class ResponseData<T> implements Serializable {
/**
* 状态码:0-成功,1-失败
* */
private int code; /**
* 错误消息,如果成功可为空或SUCCESS
* */
private String msg; /**
* 返回结果数据
* */
private T data; public static ResponseData success() {
return success(null);
} public static ResponseData success(Object data) {
ResponseData result = new ResponseData();
result.setCode(0);
result.setMsg("SUCCESS");
result.setData(data);
return result;
} public static ResponseData fail(String msg) {
return fail(msg,null);
} public static ResponseData fail(String msg, Object data) {
ResponseData result = new ResponseData();
result.setCode(1);
result.setMsg(msg);
result.setData(data);
return result;
}
}

3、统一拦截接口返回数据

新建一个类GlobalResponseHandler,用注解@RestControllerAdvice,并且实现ResponseBodyAdvice接口的方法,其中方法supports可以判断哪些需要拦截,方法beforeBodyWrite可以对返回值在输出之前进行修改,从而实现返回统一的接口数据。

package com.example.response.config;

import com.alibaba.fastjson.JSON;
import com.example.response.entity.ResponseData;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; /**
* 实现ResponseBodyAdvice接口,可以对返回值在输出之前进行修改
*/
@RestControllerAdvice
public class GlobalResponseHandler implements ResponseBodyAdvice<Object> { //判断支持的类型
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
// 检查注解是否存在,存在则忽略拦截
if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnorReponseAdvice.class)) {
return false;
}
if (methodParameter.getMethod().isAnnotationPresent(IgnorReponseAdvice.class)) {
return false;
}
return true;
} @Override
public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// 判断为null构建ResponseData对象进行返回
if (o == null) {
return ResponseData.success();
}
// 判断是ResponseData子类或其本身就返回Object o本身,因为有可能是接口返回时创建了ResponseData,这里避免再次封装
if (o instanceof ResponseData) {
return (ResponseData<Object>) o;
}
// String特殊处理,否则会抛异常
if (o instanceof String) {
return JSON.toJSON(ResponseData.success(o)).toString();
}
return ResponseData.success(o);
}
}
新建自定义注解IgnorReponseAdvice
package com.example.response.config;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnorReponseAdvice {
}

4、统一异常处理

package com.example.response.exception;
import com.example.response.entity.ResponseData;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; @RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseData exceptionHandler(Exception e) {
e.printStackTrace();
return ResponseData.fail("服务器异常:" + e.getMessage());
}
}

5、新建一个测试用的实体类

package com.example.response.entity;

import lombok.Data;

@Data
public class User {
private Long userId;
private String userName;
public User(Long userId, String userName){
this.userId = userId;
this.userName = userName;
}
}

6、新建一个测试用的控制器类

package com.example.response.controller;

import com.example.response.config.IgnorReponseAdvice;
import com.example.response.entity.ResponseData;
import com.example.response.entity.User;
import org.springframework.web.bind.annotation.*; import java.util.ArrayList;
import java.util.List; @RestController
public class DemoController {
@GetMapping("user")
public User user() {
User u = new User(100L, "u1");
return u;
} @GetMapping("userList")
public List<User> userList(){
List<User> list = new ArrayList<User>();
list.add(new User(100L, "u1"));
list.add(new User(200L, "u2"));
return list;
} @GetMapping("test1")
public String test1(){
return "test1";
} @GetMapping("test2")
public ResponseData test2(){
return ResponseData.success("test2");
} @IgnorReponseAdvice
@GetMapping("test3")
public String test3() {
return "test3";
} @GetMapping("test4")
public String test4() {
Integer x = 1 / 0;
return x.toString();
} @GetMapping("test5")
public String test5() throws Exception {
throw new Exception("自定义异常信息");
}
}

7、用Postman测试

(1)请求http://localhost:8080/user,返回

{
"code": 0,
"msg": "SUCCESS",
"data": {
"userId": 100,
"userName": "u1"
}
}

(2)请求http://localhost:8080/userList,返回

{
"code": 0,
"msg": "SUCCESS",
"data": [
{
"userId": 100,
"userName": "u1"
},
{
"userId": 200,
"userName": "u2"
}
]
}

(3)请求http://localhost:8080/tes1,返回

{"msg":"SUCCESS","code":0,"data":"test1"}

(4)请求http://localhost:8080/test2,返回

{
"code": 0,
"msg": "SUCCESS",
"data": "test2"
}

(5)请求http://localhost:8080/test3,返回

test3

(6)请求http://localhost:8080/test4,返回

{
"code": 1,
"msg": "服务器异常:/ by zero",
"data": null
}

(7)请求http://localhost:8080/test5,返回

{
"code": 1,
"msg": "服务器异常:自定义异常信息",
"data": null
}

参考文章:
https://blog.csdn.net/lrt890424/article/details/83624761
https://www.cnblogs.com/Purgeyao/p/11599810.html

spring boot 2 全局统一返回RESTful风格数据、统一异常处理的更多相关文章

  1. Spring Boot 无侵入式 实现RESTful API接口统一JSON格式返回

    前言 现在我们做项目基本上中大型项目都是选择前后端分离,前后端分离已经成了一个趋势了,所以总这样·我们就要和前端约定统一的api 接口返回json 格式, 这样我们需要封装一个统一通用全局 模版api ...

  2. Spring Boot中使用Swagger2构建RESTful APIs

    关于 Swagger Swagger能成为最受欢迎的REST APIs文档生成工具之一,有以下几个原因: Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API. S ...

  3. Spring Boot中使用Swagger2构建RESTful API文档

    在开发rest api的时候,为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题: 1.由于接口众多,并且细 ...

  4. Spring Boot 中全局异常处理器

    Spring Boot 中全局异常处理器,就是把错误异常统一处理的方法.等价于Springmvc中的异常处理器. 步骤一:基于前面的springBoot入门小demo修改 步骤二:修改HelloCon ...

  5. Spring Boot中使用Swagger2构建RESTful APIs介绍

    1.添加相关依赖 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <depen ...

  6. Spring Boot中使用Swagger2生成RESTful API文档(转)

    效果如下图所示: 添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <!-- https://mvnrepository.com/artifact/io.springfox ...

  7. Spring Boot 学习笔记(六) 整合 RESTful 参数传递

    Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...

  8. spring jpa 实体互相引用返回restful数据循环引用报错的问题

    spring jpa 实体互相引用返回restful数据循环引用报错的问题 Java实体里两个对象有关联关系,互相引用,比如,在一对多的关联关系里 Problem对象,引用了标签列表ProblemLa ...

  9. Spring Boot 揭秘与实战(二) 数据缓存篇 - 快速入门

    文章目录 1. 声明式缓存 2. Spring Boot默认集成CacheManager 3. 默认的 ConcurrenMapCacheManager 4. 实战演练5. 扩展阅读 4.1. Mav ...

随机推荐

  1. Stream系列(五)Min Max Average方法使用

    最小值,最大值,平均值 EmployeeTestCase.java package com.example.demo; import lombok.Data; import lombok.ToStri ...

  2. socket解决编码解码问题

    MySocket类: import socket class MySocket(socket.socket): # 继承自socket文件中的socket类,此时socket就是父类 def __in ...

  3. Java基础面试题及答案(五)

    Java Web 64. jsp 和 servlet 有什么区别? jsp经编译后就变成了Servlet.(JSP的本质就是Servlet,JVM只能识别java的类,不能识别JSP的代码,Web容器 ...

  4. mac 终端高亮显示~

    针对terminal采用bash模式: 编辑 ~/.bash_profile, 加入以下代码: export CLICOLOR=1 export LSCOLORS=gxfxaxdxcxegedabag ...

  5. 大规模机器学习在LinkedIn预测模型中的应用实践

    预测模型在 LinkedIn 的产品中被广泛应用,如 Feed.广告.工作推荐.邮件营销.用户搜索等.这些模型在提升用户体验时起到了重要的作用.为了满足建模需求,LinkedIn 开发并且开源了 Ph ...

  6. angularJS使用ocLazyLoad实现js延迟加载

    最近开发一个系统遇到了一个问题,用angular路由一个html片段,该片段需要使用一个js插件来实现一个富文本编辑器.关键问题在于必须要在片段加载后通过js与dom元素进行绑定.一开始想当然以为直接 ...

  7. nmon脚本——对Linux服务器的监控

    继服务器被挖之后,我又开拓了另一个监控工具----nmon! Nmon可以很轻松的监控系统的CPU.内存.网络.硬盘.文件系统.NFS.高耗进程.资源和IBM Power系统的微分区的信息,还有专属的 ...

  8. KubeSphere 日志备份与恢复实践

    为什么需要日志备份 KubeSphere 日志系统使用 Fluent Bit + ElasticSearch 的日志采集存储方案,并通过 Curator 实现对 Index 的生命周期管理,定期清理久 ...

  9. luogu P2640 神秘磁石

    题目描述 1.若给他一个一维坐标系,那么他的磁力一定要在素数坐标的位置上才能发挥的最大(不管位置坐标的大小,只要是素数那么磁力就一样大) 2.若两个磁石相距为k,那么磁石间的破坏力将会达到当前磁力的峰 ...

  10. CollectionView常用的布局方式总结

    结合网上的collectionView常用布局整合的collectionView使用工具 下载地址 支持五种布局方式ZFCollectionViewLayoutType有两种ZFCollectionV ...