后台框架-统一数据格式2

在上一篇中,当在Controller类中需要返回统一格式的数据时,需要实例化一个R,有时候觉得还是不够简洁,那有没有一种方法Controller中直接返回对象,但是返回的对象统一保存到如下格式的data中?

ResponseBodyAdvice

ResponseBodyAdvice 是 Spring MVC 框架中的一个接口,它允许你在响应体被写入之前对其进行处理。这对于实现自定义的响应格式、压缩响应、加密响应等场景非常有用。

ResponseBodyAdvice 接口有两个主要方法:

supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType): 这个方法用于判断当前 ResponseBodyAdvice 是否适用于特定的方法返回类型和 HTTP 消息转换器类型。如果返回 true,则 beforeBodyWrite 方法将被调用;如果返回 false,则不会被调用。

beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response): 这个方法在响应体被写入之前被调用。你可以在这个方法中对响应体进行修改,例如修改响应头、修改响应体内容等。这个方法的返回值将作为最终的响应体被写入。

要使用 ResponseBodyAdvice,你需要创建一个类并实现这个接口,然后将其注册为一个 Spring Bean。下面是一个简单的示例:

@ControllerAdvice

public class CustomResponseBodyAdvice implements ResponseBodyAdvice {

复制代码
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    // 根据需要判断是否应用到指定的方法返回类型和转换器类型
    return true;
}

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                              Class<? extends HttpMessageConverter<?>> selectedConverterType,
                              ServerHttpRequest request, ServerHttpResponse response) {
    // 在这里对响应体进行处理,例如包装成自定义的响应格式
    CustomResponseWrapper customResponse = new CustomResponseWrapper(body);
    return customResponse;
}

}

以下为示例代码:

java 复制代码
package org.example.web.web;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.example.web.model.R;
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.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Map;

/**
 * 对controller 层中 ResponseBody 注解方法,进行增强拦截
 */
@ControllerAdvice
public class ResultResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 返回true表示对所有Controller的返回值进行处理
        return true;
    }

    /**
     * 如果开启,就会对返回结果进行处理
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        // 设置响应类型为json
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
        if (body instanceof R) {
            // 如果body返回的是ResultMsg类型的对象,不进行增强处理
            return body;
        }
        if (body instanceof String) {
            // 如果body返回的是String类型的对象,单独处理
            return toJson(body);
        }
        if (body instanceof Map) {
            // 对异常进行统一处理
            Map<String, Object> map = (Map<String, Object>) body;
            if (map.containsKey("code") && map.containsKey("message")) {
                if ((int)map.get("code") == 200) {
                    return R.ok(map.get("message").toString());
                } else {
                    return R.error((int)map.get("code"), map.get("message").toString());
                }
            } else {
                return R.ok(map);
            }
        }
        return R.ok(body);
    }

    private Object toJson(Object body) {
        try {
            return new ObjectMapper().writeValueAsString(R.ok(body));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("无法转发json格式", e);
        }
    }
}

示例

这样当在Controller中类似这样的处理时,返回的结果就更加简洁了。

java 复制代码
    @RequestMapping("/user")
    @ResponseBody
    public R<User> user() {
        User user = User.builder().id("1").username("test").name("张三").age(20).createTime(new Date()).build();
        return R.ok(user);
    }

    @RequestMapping("/user2")
    @ResponseBody
    public User user2() {
        return User.builder().id("1").username("test").name("张三").age(20).createTime(new Date()).build();
    }

浏览器访问截图如下:

可见这种写法更简洁统一。

相关推荐
JH30735 小时前
SpringBoot 优雅处理金额格式化:拦截器+自定义注解方案
java·spring boot·spring
qq_12498707539 小时前
基于SSM的动物保护系统的设计与实现(源码+论文+部署+安装)
java·数据库·spring boot·毕业设计·ssm·计算机毕业设计
Coder_Boy_9 小时前
基于SpringAI的在线考试系统-考试系统开发流程案例
java·数据库·人工智能·spring boot·后端
2301_818732069 小时前
前端调用控制层接口,进不去,报错415,类型不匹配
java·spring boot·spring·tomcat·intellij-idea
汤姆yu12 小时前
基于springboot的尿毒症健康管理系统
java·spring boot·后端
暮色妖娆丶12 小时前
Spring 源码分析 单例 Bean 的创建过程
spring boot·后端·spring
biyezuopinvip13 小时前
基于Spring Boot的企业网盘的设计与实现(任务书)
java·spring boot·后端·vue·ssm·任务书·企业网盘的设计与实现
JavaGuide14 小时前
一款悄然崛起的国产规则引擎,让业务编排效率提升 10 倍!
java·spring boot
figo10tf14 小时前
Spring Boot项目集成Redisson 原始依赖与 Spring Boot Starter 的流程
java·spring boot·后端
zhangyi_viva15 小时前
Spring Boot(七):Swagger 接口文档
java·spring boot·后端