全局统一返回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. SpringBoot学习(六)—— springboot快速整合RabbitMQ

    目录 Rabbit MQ消息队列 简介 Rabbit MQ工作模式 交换机模式 引入RabbitMQ队列 代码实战 Rabbit MQ消息队列 @ 简介 优点 erlang开发,并发能力强. 社区活跃 ...

  2. Rust入坑指南:鳞次栉比

    很久没有挖Rust的坑啦,今天来挖一些排列整齐的坑.没错,就是要介绍一些集合类型的数据类型."鳞次栉比"这个标题是不是显得很有文化? 在Rust入坑指南:常规套路一文中我们已经介绍 ...

  3. OSI层次模型

    ISO:国际标准化组织 层(layer):描述所有的有效的通讯过程,并把逻辑上的组叫做层. 分层优点: 促进标准化工作,允许各个供应商进行开发 各层之间相互独立,把网络操作分成低复杂度性单元 灵活性好 ...

  4. easywechat微信开发SDK之小微商户进件(二)

    正式开始进件之前需要准备几个东西 1.服务商商户号 2.API密钥 微信服务商后台中设置 3.APIv3密钥 微信服务商后台中设置 4.API证书路径  登录服务商后台下载  生成证书官方又文档的 很 ...

  5. 【Android - 进阶】之Drawable简介

    Drawable是什么?Android给我们的解释是:“A general abstraction for 'something that can be drawn'.”,翻译过来就是:对于可以绘制的 ...

  6. Bootstrap 元素居中设置

    一.Bootstrap水平居中 1. 文本:class ="text-center" 2. 图片居中:class = "center-block" 3.其他元素 ...

  7. 你知道,HTTPS用的是对称加密还是非对称加密?

    1.引言 随着互联网安全意识的普遍提高,对安全要求稍高的应用中,HTTPS的使用是很常见的,甚至在1年前,苹果公司就将使用HTTPS作为APP上架苹果应用市场的先决条件之一(详见<苹果即将强制实 ...

  8. 第五章 初始jQuery

    jQuery与JavaScript: jQuery的用途: 访问和操作DOM元素: 控制页面样式: 对页面事件的处理: 方便地使用jQuery插件: 与Ajax技术的完美结合: jQuery的优势: ...

  9. Python3 函数基础1

    目录 定义函数 定义函数的三种形式 空函数 有参函数 无参函数 函数的调用 函数的返回值 函数的参数 形参 (parameter) 实参(argument) 位置形参与位置实参 默认形参 关键字实参 ...

  10. Jenkins编译过程中出现ERROR_ Failed to parse POMs错误

    一.在使用jenkins编写过程中突然出现以下问题 Parsing POMs Established TCP socket on 59407 [java] $ java -cp /var/lib/je ...