赞
踩
项目开发中,经常需要后端通常要给前端返回数据,后端程序员也经常会对数据进行自行封装,如果没有一个统一的规范,每个人都会自定义返回格式,这样一整,前端就会懵逼,骂娘,为了规避这种情况,就需要统一规范,统一给出相应数据格式,本文带你来看看springboot是如何实现的。
参考的博客:SpringBoot 如何统一后端返回格式?老鸟们都是这样玩的! - 掘金
- @GetMapping(value = "/hello1")
- public String test5(){
- return "hello world";
- }
http://localhost:8080/hello1
hello world
- @GetMapping(value = "/hello2")
- public ValidVO test6(){
- ValidVO vo = new ValidVO();
- vo.setName("zhangsan");
- vo.setSex("男");
- return vo;
- }
http://localhost:8080/hello2
- {
- "id": null,
- "appId": null,
- "name": "zhangsan",
- "email": null,
- "sex": "男",
- "level": null
- }
- @GetMapping(value = "/hello3")
- public void test7(){
- throw new RuntimeException("asdf");
- }
http://localhost:8080/hello3
- {
- "timestamp": "2021-12-08T09:11:51.371+00:00",
- "status": 500,
- "error": "Internal Server Error",
- "message": "",
- "path": "/hello3"
- }
这里我们采用spring里面的@RestControllerAdvice+自定义注解的形式来实现。
具体思路如下。
这里我们就要思考,一个标准的响应都有哪些信息。
这里我们采用大多数公司采用的格式。
- {
- "code":"0",
- "msg":"成功",
- "data":[{
- "name":"张三",
- "age":"31"
- }]
- }
响应码的作用是让人快速知道返回的结果状态,见名知意。通常分为三大类,成功,失败,异常。
一些项目会有更专业的响应码,会对异常信息和相对应的错误码绑定,通过报出的错误码,查询错误码手册来获知项目的报错内容,从而定位问题,避免盲目。这样也使代码更优雅美观。
- @Data
- public class CommonResp<T> implements Serializable {
- private static final long serivalVersionUID = 1L;
-
- /**
- * 响应码
- */
- private String code = "0";
-
- /**
- * 响应信息
- */
- private String msg = "success";
-
- /**
- * 响应消息体
- */
- private T data;
-
- private CommonResp(){
- this.code = ResponseCodeEnum.SUCCESS.getCode();
- this.msg = ResponseCodeEnum.SUCCESS.getMsg();
- }
-
- private static CommonResp success(Object data){
- CommonResp result = new CommonResp();
- result.setData(data);
- return result;
- }
- }
springboot提供了一个接口ResponseBodyAdvice。
这个接口是起什么作用呢?
先看一波源码,如下
- /**
- *Allows customizing the response after the execution of an @ResponseBody or a
- *ResponseEntity controller method but before the body is written with an
- *HttpMessageConverter.
- *Implementations may be registered directly with RequestMappingHandlerAdapter and
- *ExceptionHandlerExceptionResolver or more likely annotated with @ControllerAdvice in
- *which case they will be auto-detected by both.
- *Since:
- *4.1
- *Author:
- *Rossen Stoyanchev
- *Type parameters:
- *<T> – the body type
- */
- public interface ResponseBodyAdvice<T> {
-
- /**
- * Whether this component supports the given controller method return type
- * and the selected {@code HttpMessageConverter} type.
- * @param returnType the return type
- * @param converterType the selected converter type
- * @return {@code true} if {@link #beforeBodyWrite} should be invoked;
- * {@code false} otherwise
- */
- boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
-
- /**
- * Invoked after an {@code HttpMessageConverter} is selected and just before
- * its write method is invoked.
- * @param body the body to be written
- * @param returnType the return type of the controller method
- * @param selectedContentType the content type selected through content negotiation
- * @param selectedConverterType the converter type selected to write to the response
- * @param request the current request
- * @param response the current response
- * @return the body that was passed in or a modified (possibly new) instance
- */
- @Nullable
- T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType,
- Class<? extends HttpMessageConverter<?>> selectedConverterType,
- ServerHttpRequest request, ServerHttpResponse response);
-
- }
来我给你翻译翻译:拦截Controller方法的返回值,统一处理返回值/响应体,一般用来统一返回格式,加解密,签名等等。
那么这个玩意怎么用呢?
我们只需实现这个接口,即可。
- @RestControllerAdvice
- public class CommonRespAdvice implements ResponseBodyAdvice<Object>{
-
- @Override
- public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
- boolean hasMethodAnnotation = returnType.hasMethodAnnotation(WrapCommonResp.class);
- if(!hasMethodAnnotation){
- WrapCommonResp wrapCommonResp = returnType.getMethod() == null ? null : returnType.getMethod().getDeclaringClass().getAnnotation(WrapCommonResp.class);
- if(wrapCommonResp != null){
- hasMethodAnnotation = true;
- }
- }
- return hasMethodAnnotation;
- }
-
- @Override
- public Object beforeBodyWrite(Object obj, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
- if(obj instanceof String){
- return JSON.toJSONString(CommonResp.success(obj));
- }
- return CommonResp.success(obj);
- }
- }
以上还涉及到一个注解:@RestControllerAdvice
这个注解是是 @RestController注解的增强,可以实现三个方面的功能:
- if(obj instanceof String){
- return JSON.toJSONString(CommonResp.success(obj));
- }
注:这段代码一定要加,因为springboot对于string类型是直接返回的。
- {
- "code": "0",
- "msg": "success",
- "data": {
- "id": null,
- "appId": null,
- "name": "zhangsan",
- "email": null,
- "sex": "男",
- "level": null
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。