网站首页 > 技术文章 正文
一、返回值格式统一
1.1 返回值介绍
- 在使用controller对外提供服务的时候,很多时候都需要统一返回值格式,例如
{
"status": true,
"message": null,
"code": "200",
"data": {
"name": "json",
"desc": "json返回值"
}
}
- 如果不使用全局统一返回,就需要写一个工具类,然后controller返回对应的对象
@Data
public class ResponseData {
private boolean status;
private String message;
private String code;
private Object data;
}
@RequestMapping("/foo")
public ResponseData foo() {
// 或者使用工具类返回,根据业务设置值
return new ResponseData();
}
- 除了上述方法,可以对返回值进行统一处理,不需要对所有controller都使用一个返回值,controller只需要返回原始值,处理器会对返回值进行封装
- 同时也可以添加自定义注解,此注解用于忽略返回值封装,按照controller原始值返回
1.2 基础类功能
- org.springframework.web.method.support.HandlerMethodReturnValueHandler使用不同策略处理从调用处理程序方法的返回值策略处理顶层接口,自定义返回值格式需要实现此接口supportsReturnType:设置支持返回值类型handleReturnValue:处理返回值基础参数
- org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter请求映射处理适配,包含了参数、返回值处理器等信息HandlerMethodReturnValueHandlerComposite内部维护了HandlerMethodReturnValueHandler列表
可以自定义注解,用于类或者方法级别忽略返回值封装
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreResponseWrapper {
}
- org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor属于HandlerMethodReturnValueHandler子类主要功能是对请求和响应体的做处理的方法所有属于RequestResponseBodyMethodProcessor的子类都需要替换为自定义返回值处理
- 实现原理就是,在bean初始化的时候,获取到所有处理器数组,然后将所有是RequestResponseBodyMethodProcessor处理器子类对返回值处理的过程替换为自定义处理器处理
- 这样当调用对应返回值处理器时,将会使用到自定义的返回值处理器,也就是所有返回值都会按照规定的进行处理
1.3 基础实现
- 创建普通springboot项目,项目创建在此不做说明
- 创建类实现HandlerMethodReturnValueHandler接口,主要用于实现自定义返回值内容,不需要注入容器
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreResponseWrapper {
}
- 创建类实现InitializingBean,在初始化时调用,需要注入到容器中,否则Spring无法管理
import java.util.ArrayList;
import java.util.List;
@Component
public class ResponseBodyWrapFactoryBean implements InitializingBean {
private final RequestMappingHandlerAdapter adapter;
@Autowired
public ResponseBodyWrapFactoryBean(RequestMappingHandlerAdapter adapter) {
this.adapter = adapter;
}
@Override
public void afterPropertiesSet() throws Exception {
List<HandlerMethodReturnValueHandler> returnValueHandlers = adapter.getReturnValueHandlers();
if (returnValueHandlers.size() > 0) {
// 将内置的返回值处理器进行替换
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(returnValueHandlers);
decorateHandlers(handlers);
adapter.setReturnValueHandlers(handlers);
}
}
/**
* 将所有RequestResponseBodyMethodProcessor返回值处理器替换为自定义的返回值处理器
*
* @author tianxincode@163.com
* @since 2020/10/12
*/
private void decorateHandlers(List<HandlerMethodReturnValueHandler> handlers) {
for (HandlerMethodReturnValueHandler handler : handlers) {
if (handler instanceof RequestResponseBodyMethodProcessor) {
// 替换为自定义返回值处理器
ResponseBodyWrapHandler decorator = new ResponseBodyWrapHandler(handler);
int index = handlers.indexOf(handler);
handlers.set(index, decorator);
break;
}
}
}
}
- 创建controller信息,例如此处map不需要封装,按照原来格式响应
@RestController
@RequestMapping("/unify")
public class UnifyReturnValueController {
@RequestMapping("string")
public String stringHandler(){
return "接收成功了";
}
@RequestMapping("/json")
public JSONObject jsonHandler(){
JSONObject object = new JSONObject();
object.put("name", "json");
object.put("desc", "json返回值");
return object;
}
@RequestMapping("/map")
@IgnoreResponseWrapper
public Map<String, Object> mapHandler(){
Map<String, Object> map = new HashMap<>(10);
map.put("name", "map");
map.put("desc", "map返回值");
return map;
}
@RequestMapping("/list")
public List<Object> listHandler(){
List<Object> data = new ArrayList<>();
data.add(100);
data.add(95);
data.add(99);
return data;
}
}
1.4 测试信息
- 测试json(有封装)
{
"status": true,
"message": null,
"code": "200",
"data": {
"name": "json",
"desc": "json返回值"
}
}
- 测试map(无封装)
{
"name": "map",
"desc": "map返回值"
}
- 别的方法测试一样
二、附录说明
- 项目结构参考红框部分,别的忽略
2.除了对返回值进行全局统一,也可以对异常进行全局处理和按照统一格式返回
猜你喜欢
- 2024-12-25 Spring Boot整合Spring Cloud GateWay代理第三方应用的调用接口?
- 2024-12-25 Java 近期新闻:Hibernate 6.0、JobRunr 5.0、JHipster 7.8.0
- 2024-12-25 Keycloak Servlet Filter Adapter使用
- 2024-12-25 如何在Spring Boot中保证RESTful接口的安全性?
- 2024-12-25 Java项目实战第6天:登录业务的实现
- 2024-12-25 JavaEE概述总结:Servlet生命周期+JSP内置对象
- 2024-12-25 SpringBoot 无感刷新 Token springboot的token
- 2024-12-25 若依开发框架解析笔记(7)-jwt的应用
- 2024-12-25 Spring MVC中提供了哪些扩展机制?如何使用这些扩展机制?
- 2024-12-25 49个Spring经典面试题总结(附带答案)
- 1509℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 526℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 492℃MySQL service启动脚本浅析(r12笔记第59天)
- 472℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 469℃启用MySQL查询缓存(mysql8.0查询缓存)
- 450℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 429℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 426℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)