spring boot 2 全局统一返回RESTful风格数据、统一异常处理
全局统一返回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);
}
}
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风格数据、统一异常处理的更多相关文章
- Spring Boot 无侵入式 实现RESTful API接口统一JSON格式返回
前言 现在我们做项目基本上中大型项目都是选择前后端分离,前后端分离已经成了一个趋势了,所以总这样·我们就要和前端约定统一的api 接口返回json 格式, 这样我们需要封装一个统一通用全局 模版api ...
- Spring Boot中使用Swagger2构建RESTful APIs
关于 Swagger Swagger能成为最受欢迎的REST APIs文档生成工具之一,有以下几个原因: Swagger 可以生成一个具有互动性的API控制台,开发者可以用来快速学习和尝试API. S ...
- Spring Boot中使用Swagger2构建RESTful API文档
在开发rest api的时候,为了减少与其他团队平时开发期间的频繁沟通成本,传统做法我们会创建一份RESTful API文档来记录所有接口细节,然而这样的做法有以下几个问题: 1.由于接口众多,并且细 ...
- Spring Boot 中全局异常处理器
Spring Boot 中全局异常处理器,就是把错误异常统一处理的方法.等价于Springmvc中的异常处理器. 步骤一:基于前面的springBoot入门小demo修改 步骤二:修改HelloCon ...
- Spring Boot中使用Swagger2构建RESTful APIs介绍
1.添加相关依赖 <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --> <depen ...
- Spring Boot中使用Swagger2生成RESTful API文档(转)
效果如下图所示: 添加Swagger2依赖 在pom.xml中加入Swagger2的依赖 <!-- https://mvnrepository.com/artifact/io.springfox ...
- Spring Boot 学习笔记(六) 整合 RESTful 参数传递
Spring Boot 学习笔记 源码地址 Spring Boot 学习笔记(一) hello world Spring Boot 学习笔记(二) 整合 log4j2 Spring Boot 学习笔记 ...
- spring jpa 实体互相引用返回restful数据循环引用报错的问题
spring jpa 实体互相引用返回restful数据循环引用报错的问题 Java实体里两个对象有关联关系,互相引用,比如,在一对多的关联关系里 Problem对象,引用了标签列表ProblemLa ...
- Spring Boot 揭秘与实战(二) 数据缓存篇 - 快速入门
文章目录 1. 声明式缓存 2. Spring Boot默认集成CacheManager 3. 默认的 ConcurrenMapCacheManager 4. 实战演练5. 扩展阅读 4.1. Mav ...
随机推荐
- Amazon Lightsail部署LAMP应用程序之部署实验室基础架构
一.在Lightsail中创建LAMP堆栈实例 1.在AWS管理控制台的"服务"下拉选项中单击"Lightsail". 2.在语言方面选择 "英语&q ...
- linux 进程简介
进程相关知识简介 进程定义: 一个运行中的程序即一个process task struct: 内核存储进程信息的固定格式称为task struct,task struct记录了例如该进程内存下一跳位置 ...
- day 36 初始前端 html语言
参考博客https://www.cnblogs.com/majj/p/9056951.html进行学习 html标签 特征: .空白折叠现象 .对空格和换行不敏感 .标签要严格封闭 p标签的嵌套 多注 ...
- Git使用和介绍-基础指令
转载请标明出处:http://blog.csdn.net/shensky711/article/details/52210625 本文出自: [HansChen的博客] 查看已有配置 取消已有的配置 ...
- Java核心技术第八章-泛型
摘要 本文根据<Java核心技术 卷一>一书的第八章总结而成,部分文章摘抄书内,作为个人笔记. 文章不会过于深入,望读者参考便好. 为什么要使用泛型程序设计 泛型程序设计(Generic ...
- 2019-2020-1 20199304《Linux内核原理与分析》第四周作业
第三章 MenuOs的构造 一.前情回顾 计算机的三大法宝: -存储程序计算机 -函数调用堆栈 -中断 操作系统的两把宝剑: -中断上下文的切换(保存现场和恢复现场) -进程上下文的切换 二.3.1 ...
- 【nodejs原理&源码赏析(3)】欣赏手术级的原型链加工艺术
[摘要] 学习经典代码中的prototype加工 示例代码托管在:http://www.github.com/dashnowords/blogs 好的代码都差不多,烂的代码却各有各的烂法. 一. 概述 ...
- 快速理解spark-on-k8s中的external-shuffle-service
[摘要] external-shuffle-service是Spark里面一个重要的特性,有了它后,executor可以在不同的stage阶段动态改变数量,大大提升集群资源利用率.但是这个特性当前在k ...
- JAVA学习第一课-手工笔记
JVM:JAVA虚拟机,JAVA核心,跨平台,作用是翻译. JRE:运行环境,包含JVM和运行的核心类库. JDK:全新开发使用,包含JRE,编译工具: 核心是JVM 以下是关系库 安装路径不要有空格 ...
- 转:org.apache.maven.archiver.MavenArchiver.getManifest错误
eclipse导入新的maven项目时,pom.xml第一行报错: org.apache.maven.archiver.MavenArchiver.getManifest(org.apache.mav ...