龙空技术网

SpringBoot @RestControllerAdvice注解对返回值统一封装

Java那点事儿 1828

前言:

目前你们对“javaif中return”大约比较着重,你们都想要知道一些“javaif中return”的相关内容。那么小编也在网络上网罗了一些对于“javaif中return””的相关内容,希望各位老铁们能喜欢,小伙伴们一起来学习一下吧!

目录一. 需求场景

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

二. 前期准备

⏹获取状态码的接口

public interface IStatusCode {     int getCode();    String getMsg();}

⏹响应状态码的枚举类

import lombok.AllArgsConstructor;import lombok.Getter;@Getter@AllArgsConstructorpublic 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@AllArgsConstructorpublic enum BusinessCodeEnum implements IStatusCode {     APP_ERROR(2000, "业务异常"),    PRICE_ERROR(2001, "价格异常");    private int code;    private String msg;}

⏹自定义业务异常类

import lombok.Getter;@Getterpublic 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(                // :o:判断相应的类型是否为ResultVo类型                methodParameter.getParameterType().isAssignableFrom(ResultVo.class),                // :o:判断响应的方法上是否包含 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类型,无需包装,直接返回数据给前台

标签: #javaif中return