SpringBoot @RestControllerAdvice注解对返回值统一封装的处理方法

目录
  • 一. 需求场景
  • 二. 前期准备
  • 三. 使用@RestControllerAdvice对响应进行增强
  • 四. 效果
    • 4.1 直接返回List
    • 4.2 标记NotControllerResponseAdvice注解后返回List
    • 4.3 直接返回字符串
    • 4.4 直接返回ResultVo类型数据
  • 参考资料:

一. 需求场景

如下图所示,后台向前台响应数据的时候,所有的数据都需要放入自定义的封装Entity才返回给前台。现在想要每个Controller中的方法将原数据直接返回,然后通过某种方法统一封装处理。

二. 前期准备

⏹获取状态码的接口

public interface IStatusCode {

    int getCode();

    String getMsg();
}

⏹响应状态码的枚举类

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ResultCodeEnum implements IStatusCode {

    SUCCESS(1000, "请求成功"),
    FAILED(1001, "请求失败"),
    VALIDATE_ERROR(1002, "参数校验失败"),
    RESPONSE_PACK_ERROR(1003, "response返回包装失败");

    private int code;
    private String msg;
}

⏹业务状态码的枚举类

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum BusinessCodeEnum implements IStatusCode {

    APP_ERROR(2000, "业务异常"),
    PRICE_ERROR(2001, "价格异常");

    private int code;
    private String msg;
}

⏹自定义业务异常类

import lombok.Getter;

@Getter
public class BusinessException extends RuntimeException {

    private int code;

    private String msg;

    // 手动设置异常
    public BusinessException(IStatusCode codeEnum, String message) {
        // message用于用户设置抛出错误详情
        super(message);
        // 状态码
        this.code = codeEnum.getCode();
        // 状态码配套的msg
        this.msg = codeEnum.getMsg();
    }

    // 默认异常使用APP_ERROR状态码
    public BusinessException(String message) {
        super(message);
        this.code = BusinessCodeEnum.APP_ERROR.getCode();
        this.msg = BusinessCodeEnum.APP_ERROR.getMsg();
    }
}

⏹自定义注解,标记该注解的方法不进行响应增强
让我们的方法更加灵活,可以选择增强封装或者不增强。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NotControllerResponseAdvice {
}

三. 使用@RestControllerAdvice对响应进行增强

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

import java.util.Arrays;
import java.util.List;

// 对指定包下面的Controller进行增强
@RestControllerAdvice(basePackages = {"com.example.jmw.controller"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> converterType) {

        List<Boolean> judgeResultList = Arrays.asList(
                // 判断相应的类型是否为ResultVo类型
                methodParameter.getParameterType().isAssignableFrom(ResultVo.class),
                // 判断响应的方法上是否包含 NotControllerResponseAdvice 注解
                methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class)
        );

        // 若包含其中一项,则不进行封装
        return !judgeResultList.contains(true);
    }

    @Override
    public Object beforeBodyWrite(Object body
            , MethodParameter returnType
            , MediaType selectedContentType
            , Class<? extends HttpMessageConverter<?>> selectedConverterType
            , ServerHttpRequest request
            , ServerHttpResponse response
    ) {

        // String类型不能直接包装
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultVo里后转换为json串进行返回
                return objectMapper.writeValueAsString(ResultVo.build(body));
            } catch (JsonProcessingException e) {
            	// 抛出自定义的业务异常
                throw new BusinessException(ResultCodeEnum.RESPONSE_PACK_ERROR, e.getMessage());
            }
        }

        // 否则直接包装成ResultVo返回
        return ResultVo.build(body);
    }
}

四. 效果

4.1 直接返回List

@Controller
@RequestMapping("/test12")
public class Test12Controller {

    @PostMapping("/test")
    @ResponseBody
    public List<String> test() {

        return Arrays.asList("1", "2", "3");
    }
}

⏹List被包装之后返回给前台

4.2 标记NotControllerResponseAdvice注解后返回List

List未被包装,直接返回数据给前台

4.3 直接返回字符串

4.4 直接返回ResultVo类型数据

⏹返回的就是ResultVo类型,无需包装,直接返回数据给前台

参考资料:

正规军springboot如何处理:参数校验、统一异常、统一响应

到此这篇关于SpringBoot @RestControllerAdvice注解对返回值统一封装的文章就介绍到这了,更多相关SpringBoot返回值统一封装内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 关于springboot的接口返回值统一标准格式

    目录 一.目标 二.为什么要对springboot的接口返回值统一标准格式? 第一种格式:response为String 第二种格式:response为Objct 第三种格式:response为void 第四种格式:response为异常 三.定义response的标准格式 四.初级程序员对response代码封装 步骤1:把标准格式转换为代码 步骤2:把状态码存在枚举类里面 步骤3:加一个体验类 五.高级程序员对response代码封装 步骤1:采用ResponseBodyAdvice技术来实

  • Springboot项目异常处理及返回结果统一

    目录 背景 返回结果定义 异常的定义 异常的处理 返回结果的处理 完整代码 使用示例 背景 在创建项目的初期,我们需要规范后端返回的数据结构,以便更好地与前端开发人员合作. 比如后端返回的数据为: {  "msg": "请跳转登陆页面", } 此时前端无法确定后端服务的处理结果是成功的还是失败的.在前端展示页面,成功与失败的展示是要作区分的,甚至不同的成功或失败结果要做出不同的展现效果,这也就是我们为什么要对返回结果做出统一规范的原因. 返回结果定义 public

  • springboot中用fastjson处理返回值为null的属性值

    我们先来看代码: @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() { FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter()

  • JS在Chrome浏览器中showModalDialog函数返回值为undefined的解决方法

    本文实例讲述了JS在Chrome浏览器中showModalDialog函数返回值为undefined的解决方法.分享给大家供大家参考,具体如下: 主页面: <script type="text/javascript"> function SelectGroupCust() { var temp = window.showModalDialog("Default2.aspx?xx=" + Date(), "", "dialog

  • php读取mssql的ntext字段返回值为空的解决方法

    本文实例讲述了php读取mssql的ntext字段返回值为空的解决方法.分享给大家供大家参考.具体分析如下: 今天在使用php连接mssql数据库时发现ntext字段的内容无法显示,经过查询发现ntext字段在php中不被支持,解决办法我们只要把ntext字段改成text即可解决了. 如果是表里面没有ntext字段,可以用以下代码: 复制代码 代码如下: <?php  // Connect to MSSQL  $link = mssql_connect('KALLESPCSQLEXPRESS',

  • PHP调用存储过程返回值不一致问题的解决方法分析

    本文实例讲述了PHP调用存储过程返回值不一致问题的解决方法.分享给大家供大家参考,具体如下: 今天遇一个同学聊存储过程返回值经常得到意外的值为null, 因为白天有事,晚上给做一个实验放在这里供有相应问题的同学查看一下. 存储过程: delimiter// createprocedureusp_s2(outpar1int) begin selectinet_ntoa(ip),portfromproxy_listlimit5; selectcount(*)intopar1fromproxy_lis

  • C#获取存储过程返回值和输出参数值的方法

    1.获取Return返回值 复制代码 代码如下: //存储过程//Create PROCEDURE MYSQL//     @a int,//     @b int//AS//     return @a + @b//GOSqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString());conn.Open();SqlCommand MyC

  • JQuery异步获取返回值中文乱码的解决方法

    用jqgrid异步获取列表值,遇到个问题,服务器端从数据库取到的数据没有出现中文乱码问题(日志打出来是没有乱码的),但是异步传到客户的时候却出现了乱码. 服务器端已经编码过了(UTF-8编码).开始一直怀疑是客户端的问题,比如客户端和服务器端编码不一致啊,也怀疑是不是jqGrid工具函数中少配了 contentType: "application/x-www-form-urlencoded; charset=utf-8",   等等问题. 结果都不是,纠结了几个小时,后来经过大牛的提醒

  • SpringBoot全局Controller返回值格式统一

    目录 一.返回值格式统一 1.返回值介绍 2.基础类功能 3.基础实现 二.附录说明 一.返回值格式统一 1.返回值介绍 在使用controller对外提供服务的时候,很多时候都需要统一返回值格式,例如 { "status": true, "message": null, "code": "200", "data": { "name": "json", "d

  • spring通过filter,Interceptor统一处理ResponseBody的返回值操作

    项目中有一个需求,需要统一处理一下@ResponseBody注解的返回值(比如打印),在网上找了一下,有建议用AOP来做的,但是个人认为项目中用多个AOP并不优雅:通过google,找到了spring的ResponseBodyAdvice接口,用来对返回体做统一处理. 例如:统一打印返回体中的内容 @ControllerAdvice(basePackages = "cc.openwiki.controller.biz") public class LogResponseAdvice i

随机推荐