SpringBoot define un elegante marco de respuesta API Restful unificado global seis

No hay muchos chismes, continúe optimizando el marco de respuesta global unificado de la API Restful para hacer que la interfaz general del proyecto sea escalable.

Si no ha leído los artículos anteriores, lea los artículos anteriores.

SpringBoot define un elegante marco de respuesta de API Restful unificado global

SpringBoot define un elegante marco de respuesta de API Restful unificado global 2

SpringBoot define un marco de respuesta de API Restful unificado global elegante tres

SpringBoot define un elegante marco de respuesta de API Restful unificado global cuatro

SpringBoot define un marco de respuesta de API Restful unificado global elegante cinco

Aquí hay una charla sobre la última versión y algunos problemas que deben solucionarse.

 @PostMapping("/add/UserApiCombo")
    public R addApiCombo(@RequestBody @Validated UserApplyApiComboDto userApplyApiComboDto) {
    
    
        userApiComboService.addApiCombo(userApplyApiComboDto);
        return R.success();
    }

Veamos este código, qué está mal. Devolvimos un conjunto de resultados encapsulados unificados R, pero controllerno es fácil escribir todo lo siguiente.

  1. El contenido devuelto no es lo suficientemente claro.
  2. Toda controllerescritura de esta manera aumenta la carga de trabajo de la duplicación.

Podemos optimizar así:

Spirng proporciona ResponseBodyAdviceuna interfaz que admite el procesamiento del resultado de retorno de la interfaz antes de que el convertidor de mensajes realice la conversión y, en combinación con @ControllerAdvicelas anotaciones, las funciones anteriores se pueden admitir fácilmente.

package cn.soboys.springbootrestfulapi.common.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.soboys.springbootrestfulapi.common.error.ErrorDetail;
import cn.soboys.springbootrestfulapi.common.resp.R;
import lombok.extern.slf4j.Slf4j;
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;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/6/12 12:17 下午
 * @webSite https://github.com/coder-amiao
 * @Slf4j
 * @ControllerAdvice
 */
@Slf4j
@ControllerAdvice
public class ResponseResultHandler implements ResponseBodyAdvice<Object> {
    
    
    /**
     * supports方法: 判断是否要执行beforeBodyWrite方法,
     * true为执行,false不执行.
     * 通过该方法可以选择哪些类或那些方法的response要进行处理, 其他的不进行处理.
     *
     * @param returnType
     * @param converterType
     * @return
     */
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    
    
        return true;
    }

    /**
     * beforeBodyWrite方法: 对response方法进行具体操作处理
     * 实际返回结果业务包装处理
     *
     * @param body
     * @param returnType
     * @param selectedContentType
     * @param selectedConverterType
     * @param request
     * @param response
     * @return
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    
    
        if (body instanceof R) {
    
    
            return body;
        } else if (body == null) {
    
    
            return R.success();
        } else if (body instanceof ErrorDetail) {
    
    
            return body;
        } else if (body instanceof String) {
    
    
            return body;
        } else {
    
    
            return R.success().data(body);
        }
    }
}

En la controllerdevolución real, podemos devolver directamente el contenido de los datos

    @GetMapping("/home")
    public Student home() {
    
    

        Student s = new Student();
        s.setUserName("Tom");
        s.setAge(22);
        List hobby = new ArrayList();
        hobby.add("抽烟");
        hobby.add("喝酒");
        hobby.add("烫头");
        s.setHobby(hobby);
        s.setBalance(2229891.0892);
        s.setIdCard("420222199811207237");
        return s;
    }

La lógica de juicio de errores comerciales en nuestra versión actual no es muy amigable y necesita ser optimizada. Aquí podemos encapsular nuestras propias excepciones comerciales y
usar Assert (afirmación) para encapsular excepciones y hacer que el código sea más elegante.

De acuerdo con el principio de retorno de prioridad de error

Normalmente, nuestro código de excepción comercial se escribe así

// 另一种写法
        Order order = orderDao.selectById(orderId);
        if (order == null) {
    
    
            throw new IllegalArgumentException("订单不存在。");
        }

Después de usar la optimización de aserciones

 Order order = orderDao.selectById(orderId);
 Assert.notNull(order, "订单不存在。");

Comparando los dos métodos, es obvio que el primer método es más elegante, mientras que el segundo método es un bloque de código if {…} relativamente feo. Entonces , ¿qué hay detrás del mágico Assert.notNull() ?

Aquí está el código que necesitamos para optimizar

De hecho, muchos marcos tienen herramientas Assert , incluido JAVA JDK. SpringBoot, Spring también tiene su propio Assert
pero no se ajusta a nuestra propia lógica comercial de generación de excepciones, aquí podemos personalizar nuestra propia herramienta Assert .

Echemos un vistazo a un código fuente

public abstract class Assert {
    
    
    public Assert() {
    
    
    }

    public static void notNull(@Nullable Object object, String message) {
    
    
        if (object == null) {
    
    
            throw new IllegalArgumentException(message);
        }
    }
}

Como puede ver, Assert en realidad nos ayuda a encapsular si {...} , ¿no es asombroso? Aunque simple, es innegable que la experiencia de codificación se ha mejorado al menos un nivel.

Entonces, podemos imitar Assert y escribir una clase de aserción personalizada, pero las excepciones lanzadas después de que falla la aserción no son excepciones integradas como IllegalArgumentException , sino excepciones definidas por nosotros mismos.

  1. definir excepción pública
package cn.soboys.springbootrestfulapi.common.exception;

import cn.soboys.springbootrestfulapi.common.resp.ResultCode;
import lombok.Data;

/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/6/12 10:32 下午
 * @webSite https://github.com/coder-amiao
 */
@Data
public class BaseException extends RuntimeException {
    
    
    /**
     * 返回码
     */
    protected ResultCode resultCode;
    /**
     * 异常消息参数
     */
    protected Object[] args;

    public BaseException(ResultCode resultCode) {
    
    
        super(resultCode.getMessage());
        this.resultCode = resultCode;
    }


    public BaseException(String code, String msg) {
    
    
        super(msg);
        this.resultCode = new ResultCode() {
    
    
            @Override
            public String getCode() {
    
    
                return code;
            }

            @Override
            public String getMessage() {
    
    
                return msg;
            }

            @Override
            public boolean getSuccess() {
    
    
                return false;
            }

            ;
        };
    }

    public BaseException(ResultCode resultCode, Object[] args, String message) {
    
    
        super(message);
        this.resultCode = resultCode;
        this.args = args;
    }

    public BaseException(ResultCode resultCode, Object[] args, String message, Throwable cause) {
    
    
        super(message, cause);
        this.resultCode = resultCode;
        this.args = args;
    }

}
  1. Todas las demás excepciones heredan la excepción común
package cn.soboys.springbootrestfulapi.common.exception;


import cn.soboys.springbootrestfulapi.common.resp.ResultCode;


/**
 * @author 公众号 程序员三时
 * @version 1.0
 * @date 2023/4/29 00:15
 * @webSite https://github.com/coder-amiao
 * 通用业务异常封装
 */
public class BusinessException extends BaseException {
    
    

    
    public BusinessException(ResultCode resultCode, Object[] args, String message) {
    
    
        super(resultCode, args, message);
    }

    public BusinessException(ResultCode resultCode, Object[] args, String message, Throwable cause) {
    
    
        super(resultCode, args, message, cause);
    }

}

  1. Encapsulación de clase de excepción empresarial de aserción
public interface Assert {
    
    
    /**
     * 创建异常
     * @param args
     * @return
     */
    BaseException newException(Object... args);

    /**
     * 创建异常
     * @param t
     * @param args
     * @return
     */
    BaseException newException(Throwable t, Object... args);

    /**
     * <p>断言对象<code>obj</code>非空。如果对象<code>obj</code>为空,则抛出异常
     *
     * @param obj 待判断对象
     */
    default void assertNotNull(Object obj) {
    
    
        if (obj == null) {
    
    
            throw newException(obj);
        }
    }

    /**
     * <p>断言对象<code>obj</code>非空。如果对象<code>obj</code>为空,则抛出异常
     * <p>异常信息<code>message</code>支持传递参数方式,避免在判断之前进行字符串拼接操作
     *
     * @param obj 待判断对象
     * @param args message占位符对应的参数列表
     */
    default void assertNotNull(Object obj, Object... args) {
    
    
        if (obj == null) {
    
    
            throw newException(args);
        }
    }
}

Uso específico

/**
     * 异常返回模拟
     *
     * @return
     */
    @GetMapping("/exception")
    public Student  exception() {
    
    
        Student s = null;
        BusinessErrorCode.Sign_Error.assertNotNull(s,"secret秘钥不正确");
        return s;
    }

En los negocios, podemos lanzar excepciones de enumeración directamente de esta manera. Esto hace que el código sea mucho más simple y limpio.

El proxy se ha actualizado al proyecto de andamiaje del repositorio de github

Preste atención a la cuenta oficial, el programador continuará generando contenido de alta calidad a las tres en punto , con la esperanza de brindarle algo de inspiración y ayuda.

Supongo que te gusta

Origin blog.csdn.net/u011738045/article/details/131187834
Recomendado
Clasificación