后台框架-统一数据格式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();
    }

浏览器访问截图如下:

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

相关推荐
狂放不羁霸30 分钟前
idea | 搭建 SpringBoot 项目之配置 Maven
spring boot·maven·intellij-idea
计算机学长felix1 小时前
基于SpringBoot的“校园交友网站”的设计与实现(源码+数据库+文档+PPT)
数据库·spring boot·毕业设计·交友
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
江深竹静,一苇以航1 小时前
springboot3项目整合Mybatis-plus启动项目报错:Invalid bean definition with name ‘xxxMapper‘
java·spring boot
豪宇刘2 小时前
SpringBoot+Shiro权限管理
java·spring boot·spring
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea
2402_857589363 小时前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
杨荧3 小时前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
计算机-秋大田5 小时前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue