0
点赞
收藏
分享

微信扫一扫

shenyu修改统一出参和全局异常捕捉

一、环境

shenyu:2.5.0

二、场景

通常在业务系统需要定义统一出参,一般包括:

  1. 请求时间
  2. 请求路径
  3. 请求id
  4. 异常码
  5. 异常信息 6...

在业务代码编写过程,一般采用断言的方式将异常抛出,减少通用方法的二次解析code

在项目的异常使用的msg,shenyu使用的message,异常捕捉的异常码都统一设置为500,等等等

三、定位问题

在修改开源源码时,通常保证源码的继承性,保留原始逻辑,在此之上构建扩展

那么我看看shenyu是如何构建统一出参和异常捕捉的

通过查看plugin插件,发现统一通过ShenyuResultWrap来构造出参的

public final class ShenyuResultWrap {
    
    private ShenyuResultWrap() {
    }
    
    /**
     * Success object.
     *
     * @param exchange the exchange
     * @param object  the object
     * @return the success object
     */
    public static Object success(final ServerWebExchange exchange, final Object object) {
        return shenyuResult().result(exchange, object);
    }

    /**
     * Error object.
     *
     * @param exchange the exchange
     * @param shenyuResult  the shenyuResult
     * @param object  the object
     * @return the object
     */
    public static Object error(final ServerWebExchange exchange, final ShenyuResultEnum shenyuResult, final Object object) {
        return shenyuResult().error(exchange, shenyuResult.getCode(), shenyuResult.getMsg(), object);
    }
    
    /**
     * Error object.
     *
     * @param shenyuResult the shenyuResult
     * @param object  the object
     * @return the object
     */
    public static Object error(final ShenyuResultEnum shenyuResult, final Object object) {
        return shenyuResult().error(shenyuResult.getCode(), shenyuResult.getMsg(), object);
    }
    
    /**
     * Error object.
     *
     * @param exchange the exchange
     * @param shenyuResult the shenyuResult
     * @return the object
     */
    public static Object error(final ServerWebExchange exchange, final ShenyuResultEnum shenyuResult) {
        return shenyuResult().error(exchange, shenyuResult.getCode(), shenyuResult.getMsg(), null);
    }

    /**
     * Error object.
     *
     * @param exchange the exchange
     * @param code    the code
     * @param message the message
     * @param object  the object
     * @return the object
     */
    public static Object error(final ServerWebExchange exchange, final int code, final String message, final Object object) {
        return shenyuResult().error(exchange, code, message, object);
    }

    /**
     * shenyu result bean.
     *
     * @return the shenyu result bean.
     */
    public static ShenyuResult<?> shenyuResult() {
        return SpringBeanUtils.getInstance().getBean(ShenyuResult.class);
    }
}

发现最终是从Spring容器中获取ShenyuResult来完成构建

public interface ShenyuResult<T> {

    /**
     * The response result.
     *
     * @param exchange the exchange
     * @param formatted the formatted data that is origin data(basic、byte[]) or json string
     * @return the result object
     */
    default Object result(ServerWebExchange exchange, Object formatted) {
        return formatted;
    }

    /**
     * format the origin, default is json format except the basic and bytes.
     *
     * @param exchange the exchange
     * @param origin the origin
     * @return format origin
     */
    default Object format(ServerWebExchange exchange, Object origin) {
        // basic data or upstream data
        if (ObjectTypeUtils.isBasicType(origin) || (origin instanceof byte[])) {
            return origin;
        }
        // error result or rpc origin result.
        return JsonUtils.toJson(origin);
    }

    /**
     * the response context type, default is application/json.
     *
     * @param exchange the exchange
     * @param formatted the formatted data that is origin data(basic、byte[]) or json string
     * @return the context type
     */
    default MediaType contentType(ServerWebExchange exchange, Object formatted) {
        final ClientResponse clientResponse = exchange.getAttribute(Constants.CLIENT_RESPONSE_ATTR);
        if (Objects.nonNull(clientResponse) && clientResponse.headers().contentType().isPresent()) {
            return clientResponse.headers().contentType().get();
        }
        return MediaType.APPLICATION_JSON;
    }

    /**
     * Error t.
     *
     * @param exchange the exchange
     * @param code    the code
     * @param message the message
     * @param object  the object
     * @return the t
     */
    default T error(ServerWebExchange exchange, int code, String message, Object object) {
        return error(code, message, object);
    }

    /**
     * Error t.
     *
     * @param code    the code
     * @param message the message
     * @param object  the object
     * @return the t
     */
    default T error(int code, String message, Object object) {
        return null;
    }

查看实现类

public class DefaultShenyuResult implements ShenyuResult<DefaultShenyuEntity> {

    @Override
    public DefaultShenyuEntity error(final int code, final String message, final Object object) {
        return DefaultShenyuEntity.error(code, message, object);
    }
}

出参类是DefaultShenyuEntity

public class DefaultShenyuEntity implements Serializable {

    private static final long serialVersionUID = -2792556188993845048L;
    
    private static final int ERROR = 500;

    private Integer code;

    private String message;

    @JsonBackReference
    private Object data;

    /**
     * Instantiates a new shenyu result.
     *
     * @param code    the code
     * @param message the message
     * @param data    the data
     */
    public DefaultShenyuEntity(final Integer code, final String message, final Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * Gets code.
     *
     * @return the code
     */
    public Integer getCode() {
        return code;
    }

    /**
     * Sets code.
     *
     * @param code the code
     */
    public void setCode(final Integer code) {
        this.code = code;
    }

    /**
     * Gets message.
     *
     * @return the message
     */
    public String getMessage() {
        return message;
    }

    /**
     * Sets message.
     *
     * @param message the message
     */
    public void setMessage(final String message) {
        this.message = message;
    }

    /**
     * Gets data.
     *
     * @return the data
     */
    public Object getData() {
        return data;
    }

    /**
     * Sets data.
     *
     * @param data the data
     */
    public void setData(final Object data) {
        this.data = data;
    }

    /**
     * return error .
     *
     * @param msg error msg
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static DefaultShenyuEntity error(final String msg) {
        return error(ERROR, msg);
    }

    /**
     * return error .
     *
     * @param code error code
     * @param msg  error msg
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static DefaultShenyuEntity error(final int code, final String msg) {
        return get(code, msg, null);
    }

    /**
     * return error .
     *
     * @param code error code
     * @param msg  error msg
     * @param data the data
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static DefaultShenyuEntity error(final int code, final String msg, final Object data) {
        return get(code, msg, data);
    }

    /**
     * return timeout .
     *
     * @param msg error msg
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static DefaultShenyuEntity timeout(final String msg) {
        return error(ERROR, msg);
    }

    private static DefaultShenyuEntity get(final int code, final String msg, final Object data) {
        return new DefaultShenyuEntity(code, msg, data);
    }
}

四、解决

思路就是继承ShenyuResult和DefaultShenyuEntity,然后屏蔽不需要的参数

4.1 统一出参

public class TeddyShenyuEntity extends DefaultShenyuEntity {

    private static final long serialVersionUID = -6414981693206070036L;

    /**
     * 忽略message字段,修改成msg
     */
    @JsonIgnore
    private String message;

    /**
     * 展示异常
     */
    private String msg = "系统异常";

    private static final int ERROR = 500;

    public TeddyShenyuEntity(Integer code, String message, Object data) {
        super(code, message, data);
        this.message = message;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

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

    @Override
    public void setMessage(String message) {
        this.message = message;
    }

    /**
     * return error .
     *
     * @param msg error msg
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static TeddyShenyuEntity error(final String msg) {
        return error(ERROR, msg);
    }

    /**
     * return error .
     *
     * @param code error code
     * @param msg  error msg
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static TeddyShenyuEntity error(final int code, final String msg) {
        return get(code, msg, null);
    }

    /**
     * return error .
     *
     * @param code error code
     * @param msg  error msg
     * @param data the data
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static TeddyShenyuEntity error(final int code, final String msg, final Object data) {
        return get(code, msg, data);
    }

    /**
     * return timeout .
     *
     * @param msg error msg
     * @return {@linkplain DefaultShenyuEntity}
     */
    public static TeddyShenyuEntity timeout(final String msg) {
        return error(ERROR, msg);
    }

    private static TeddyShenyuEntity get(final int code, final String msg, final Object data) {
        return new TeddyShenyuEntity(code, msg, data);
    }

}

public class TeddyShenyuResult implements ShenyuResult<DefaultShenyuEntity> {

    @Override
    public DefaultShenyuEntity error(final int code, final String message, final Object object) {
        return TeddyShenyuEntity.error(code, message, object);
    }
}

自动配置

@Configuration
public class TeddyShenyuConfiguration {

    private static final Logger log = LoggerFactory.getLogger(TeddyShenyuConfiguration.class);

    @Bean
    @Primary
    public TeddyShenyuResult teddyShenyuResult() {
		log.info("TeddyShenyu统一出参增强")
        return new TeddyShenyuResult();
    }

}

4.2 全局异常处理

继承修改ErrorWebExceptionHandler即可,不再复述

举报

相关推荐

0 条评论