SpringBoot全局Controller返回值格式统一
目录
- 一、返回值格式统一
- 1.返回值介绍
- 2.基础类功能
- 3.基础实现
- 二、附录说明
一、返回值格式统一
1.返回值介绍
在使用controller对外提供服务的时候,很多时候都需要统一返回值格式,例如
{ "status": true, "message": null, "code": "200", "data": {"name": "json","desc": "json返回值" }}
如果不使用全局统一返回,就需要写一个工具类,然后controller返回对应的对象
@Datapublic 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原始值返回
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)@Documentedpublic @interface IgnoreResponseWrapper {}
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor
- 属于HandlerMethodReturnValueHandler子类
- 主要功能是对请求和响应体的做处理的方法
- 所有属于RequestResponseBodyMethodProcessor的子类都需要替换为自定义返回值处理
处理这样当调用对应返回值处理器时,将会使用到自定义的返回值处理器,也就是所有返回值都会按照规定的进行处理
3.基础实现
创建普通springboot项目,项目创建在此不做说明
创建类实现HandlerMethodReturnValueHandler接口,主要用于实现自定义返回值内容,不需要注入容器
import com.codecoord.unifyreturn.annotation.IgnoreResponseWrapper; import com.codecoord.unifyreturn.domain.ResponseBase; import org.springframework.core.MethodParameter; import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.method.support.HandlerMethodReturnValueHandler; import org.springframework.web.method.support.ModelAndViewContainer; public class ResponseBodyWrapHandler implements HandlerMethodReturnValueHandler {private final HandlerMethodReturnValueHandler delegate; public ResponseBodyWrapHandler(HandlerMethodReturnValueHandler delegate) {this.delegate = delegate; }@Overridepublic boolean supportsReturnType(MethodParameter returnType) {return delegate.supportsReturnType(returnType); }@Overridepublic void handleReturnValue(Object returnValue,MethodParameter returnType,ModelAndViewContainer mavContainer,NativeWebRequest webRequest) throws Exception {// 如果类或者方法含有不包装注解则忽略包装IgnoreResponseWrapper wrapper = returnType.getDeclaringClass().getAnnotation(IgnoreResponseWrapper.class); if (wrapper != null) {delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest); return; }wrapper = returnType.getMethodAnnotation(IgnoreResponseWrapper.class); if (wrapper != null) {delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest); return; }// 自定义返回格式ResponseBase responseBase = new ResponseBase(); responseBase.setStatus(true); responseBase.setCode("200"); responseBase.setData(returnValue); delegate.handleReturnValue(responseBase, returnType, mavContainer, webRequest); }}
创建类实现InitializingBean,在初始化时调用,需要注入到容器中,否则Spring无法管理
import java.util.ArrayList; import java.util.List; @Componentpublic class ResponseBodyWrapFactoryBean implements InitializingBean {private final RequestMappingHandlerAdapter adapter; @Autowiredpublic ResponseBodyWrapFactoryBean(RequestMappingHandlerAdapter adapter) {this.adapter = adapter; }@Overridepublic void afterPropertiesSet() throws Exception {List returnValueHandlers = adapter.getReturnValueHandlers(); if (returnValueHandlers.size() > 0) {// 将内置的返回值处理器进行替换List handlers = new ArrayList<>(returnValueHandlers); decorateHandlers(handlers); adapter.setReturnValueHandlers(handlers); }}/** * 将所有RequestResponseBodyMethodProcessor返回值处理器替换为自定义的返回值处理器** @author tianxincode@163.com* @since 2020/10/12*/private void decorateHandlers(List 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")@IgnoreResponseWrapperpublic Map mapHandler(){Map map = new HashMap<>(10); map.put("name", "map"); map.put("desc", "map返回值"); return map; }@RequestMapping("/list")public List
4.测试信息 测试json(有封装)
{ "status": true, "message": null, "code": "200", "data": {"name": "json","desc": "json返回值" }}
测试map(无封装)
{ "name": "map", "desc": "map返回值"}
别的方法测试一样
二、附录说明 项目结构参考红框部分,别的忽略
文章图片
除了对返回值进行全局统一,也可以对异常进行全局处理和按照统一格式返回
到此这篇关于SpringBoot全局Controller返回值格式统一的文章就介绍到这了,更多相关SpringBoot返回值格式统一内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- Activiti(一)SpringBoot2集成Activiti6
- SpringBoot调用公共模块的自定义注解失效的解决
- 解决SpringBoot引用别的模块无法注入的问题
- springboot使用redis缓存
- Swift|Swift ----viewController 中addChildViewController
- springboot整合数据库连接池-->druid
- SpringBoot中YAML语法及几个注意点说明
- springboot结合redis实现搜索栏热搜功能及文字过滤
- springboot中.yml文件的值无法读取的问题及解决
- SpringBoot整合MongoDB完整实例代码