1.hello word 一个Motan扩展

大概需要下面的三点:

  1. 实现SPI扩展点接口

    package com.weibo.api.motan.filter;
    @Spi
    public interface Filter {Response filter(Caller<?> caller, Request request);
    }
    

业务代码实现Filter

public class PlsProviderExceptionFilter implements Filter {@Overridepublic Response filter(Caller<?> caller, Request request) {//实现具体的业务逻辑}
}
  1. 实现类增加注解

    @Spi(scope = Scope.SINGLETON)  //扩展加载形式,单例或多例
    @SpiMeta(name = "motan")  //name表示扩展点的名称,根据name加载对应扩展
    @Activation(sequence = 100) //同类型扩展生效顺序,部分扩展点支持。非必填
    
    @SpiMeta(name = "pls-exception-filter")
    //sequence默认20,越大越先执行完
    @Activation(sequence = 100, key = {MotanConstants.NODE_TYPE_SERVICE})
    public class PlsProviderExceptionFilter implements Filter {//...
    }
    

  2. 增加SPI实现声明 classpath/META−INF/services/{classpath}/META-INF/services/classpath/META−INF/services/{SPI interface fullname}文件中添加对应SPI接口实现类全名。 可参照motan-core模块/META-INF/services/下的配置

    #扩展接口
    com.sxl.motan.PlsProviderExceptionFilter
    

官方对moten扩展机制介绍

filter机制是在client端与server端请求处理是都会经过的过滤机制,使用者可以通过filter来实现对请求的request和response进行定制化处理。 filter扩展的实现方式是通过上述的SPI扩展,使用中有如下问题需要注意。

1、如何使扩展的filter生效。

SPI扩展必须对应一个唯一的name,实际使用中通过name来加载扩展。一般扩展需要在配置中设置对应的name,然后自动加载。

filter扩展默认是不生效的,加载filter的方式分为强制加载和指定加载。如果需要强制生效,可以通过配置@Activation来实现,MotanConstants.NODE_TYPE_SERVICE表示在server端强制生效,MotanConstants.NODE_TYPE_REFERER表示在client端强制生效。 强制生效情况下,不管任何service都会进行filter过滤。 配置样例如下:

@Activation(key = { MotanConstants.NODE_TYPE_SERVICE, MotanConstants.NODE_TYPE_REFERER })

如果只需要在某些service中生效,则可以直接通过在basicService或者service中配置 filter="filter_name"即可,其中的filter_name就是扩展filter中声明的@SpiMeta(name = “***”)中name的值

推荐通过配置方式使用filter,减少不必要的filter装载

2.实现motan异常统一处理核心逻辑

2.1自定义异常类定义

异常枚举

用于规范异常,各个模块维护自己的异常编码。对应的异常编码可以同步 [帮助系统并给出解决方案。方便***用户查找解决***

package com.sxl.exception.errorCode;/*** 系统各平台业务异常枚举* @ClassName: com.sxl.exception.PlsBizErrorCode.java* @author: songxulin* @date :  2021-01-04 15:37* @version V1.0*/
public enum PlsBizErrorCode {/************************** 公共异常 *****************************/E_000000("000000","fail","失败"),E_000001("000001","success","成功"),E_000002("000002","parameterError","请求参数为空"),E_000003("000003","parameterInvalid","请求参数非法"),E_000004("000004","jsonError","JSON转换失败"),E_000005("000005","dbError","数据库异常"),E_000006("000006","networkError","网络异常"),E_000007("000007","unkownError","未知异常"),E_000008("000008","handleDataException","数据处理异常"),E_000009("000009","existed","数据已存在"), E_000010("000010","numberFormatException","数值转换异常"),E_000011("000011","NullPointerException","数据空指针异常"),/************************** 通用模块异常  ******************************/P_C00001("P_C00001","skuParseError","sku解析异常"),;private String code;private String name;private String desc;PlsBizErrorCode(String code, String name, String desc) {this.code = code;this.name = name;this.desc = desc;}@Overridepublic String getCode() {return code;}@Overridepublic String getName() {return name;}@Overridepublic String getDesc() {return desc;}
}
异常抽象类

异常统一继承此类

package com.sxl.exception;import com.sxl.exception.errorCode.ErrorCode;/*** 刊登系统异常抽象类* @ClassName: com.sxl.exception.AbstractException.java* @author: songxulin* @date :  2021-01-04 17:27* @version V1.0*/
public abstract class AbstractPLSException extends RuntimeException{private static final long serialVersionUID = -4470524790791804455L;private String state;private String name;private void init(String code, String name){this.state = code;this.name = name;}private void init(ErrorCode errorCode){init(errorCode.getCode(), errorCode.getName());}private AbstractPLSException(String message) {super(message);}private AbstractPLSException(String message, Throwable cause){super(message,cause);}public AbstractPLSException(String code, String name, String desc){this(desc);init(code, name);}public AbstractPLSException(String code, String name, String desc, Throwable cause{this(desc, cause);init(code, name);}public AbstractPLSException(ErrorCode errorCode){this(errorCode.getDesc());init(errorCode);}public AbstractPLSException(ErrorCode errorCode, String desc){this(desc);init(errorCode);}public AbstractPLSException(ErrorCode errorCode, Throwable cause){this(errorCode.getDesc(), cause);init(errorCode);}public String getState() {return state;}public String getName() {return name;}public String getStateMsg(){return state+":"+getMessage();}
}
自定义异常
package com.sxl.exception;import com.sxl.exception.errorCode.ErrorCode;/*** 刊登系统业务异常* @ClassName: com.sxl.exception.PlsBizException.java* @author: songxulin* @date :  2021-01-04 15:36* @version V1.0*/
public class PlsBizException extends AbstractPLSException {private static final long serialVersionUID = 5600133107550376666L;public PlsBizException(String code, String name, String desc) {super(code, name, desc);}public PlsBizException(ErrorCode errorCode, String desc) {super(errorCode,desc);}public PlsBizException(ErrorCode errorCode) {super(errorCode);}public PlsBizException(ErrorCode errorCode, Throwable cause) {super(errorCode, cause);}
}
异常枚举
package com.sxl.exception;import com.alibaba.fastjson.JSONException;
import com.sxl.exception.errorCode.ErrorCode;
import com.sxl.exception.errorCode.PlsBizErrorCode;
import java.util.HashMap;
import java.util.Map;
/*** 异常枚举* @ClassName: com.sxl.exception.ExceptionEnum.java* @author: songxulin* @date :  2021-01-04 19:38* @version V1.0*/
public enum ExceptionEnum {JSONException("JSONException", JSONException.class, PlsBizErrorCode.E_000004),NumberFormatException("NumberFormatException",NumberFormatException.class, PlsBizErrorCode.E_000010),NullPointerException("NullPointerException",NullPointerException.class, PlsBizErrorCode.E_000010),IllegalArgumentException("IllegalArgumentException",IllegalArgumentException.class,PlsBizErrorCode.E_000008),;private String name;private Class clazz;private ErrorCode errorCode;private static Map<Class,ExceptionEnum> enumMap =new HashMap<>(16);static {for (ExceptionEnum value : ExceptionEnum.values()) {enumMap.put(value.clazz,value);}}ExceptionEnum(String name, Class clazz, ErrorCode errorCode) {this.name = name;this.clazz = clazz;this.errorCode = errorCode;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Class getClazz() {return clazz;}public void setClazz(Class clazz) {this.clazz = clazz;}public ErrorCode getErrorCode() {return errorCode;}public void setErrorCode(ErrorCode errorCode) {this.errorCode = errorCode;}/*** 根据异常类获取对应异常* @param e Class 异常class* @return ExceptionEnum*/public static ExceptionEnum getByClazz(Class e){return enumMap.get(e);}
}

2.2 filter编写

package com.sxl.motan;import com.alibaba.fastjson.JSON;
import com.weibo.api.motan.common.MotanConstants;
import com.weibo.api.motan.core.extension.Activation;
import com.weibo.api.motan.core.extension.SpiMeta;
import com.weibo.api.motan.exception.MotanAbstractException;
import com.weibo.api.motan.filter.Filter;
import com.weibo.api.motan.rpc.Caller;
import com.weibo.api.motan.rpc.DefaultResponse;
import com.weibo.api.motan.rpc.Request;
import com.weibo.api.motan.rpc.Response;
import com.sxl.exception.AbstractPLSException;
import com.sxl.exception.ExceptionEnum;
import com.sxl.exception.PLSServiceException;
import com.sxl.vo.ResultVO;
import com.sxl.vo.VoHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** * @ClassName: com.sxl.motan.PlsProviderExceptionFilter.java* @author: songxulin* @date :  2021-01-04 20:09* @version V1.0*/
@SpiMeta(name = "pls-exception-filter")
//sequence默认20,越大越先执行完
@Activation(sequence = 100, key = {MotanConstants.NODE_TYPE_SERVICE})
public class PlsProviderExceptionFilter implements Filter {private final static Logger log = LoggerFactory.getLogger(PlsProviderExceptionFilter.class);@Overridepublic Response filter(Caller<?> caller, Request request) {Response response;try {response = caller.call(request);} catch (Exception e) {log.error(e.getMessage(), e);return buildExceptionResponse(e);}if (response.getException() != null) {log.error(String.format("%s,%s 调用异常",request.getAttachments().get("host"),request.getMethodName()),response.getException().getCause());return buildExceptionResponse(response);}return response;}/*** 构建异常Response* @param e 异常* @return Response*/private Response buildExceptionResponse(Exception e) {DefaultResponse response = new DefaultResponse();AbstractPLSException ex;//自定义异常if (e instanceof MotanAbstractException) {ex = getException((MotanAbstractException) e);} else {//系统未知异常ex = new PLSServiceException("", "", "系统未知异常");}response.setValue(JSON.toJSONString(formatError(ex)));return response;}/*** 获取异常类型* @param e 异常* @return AbstractPLSException*/private AbstractPLSException getException(MotanAbstractException e) {Throwable cause = e.getCause();if (cause instanceof AbstractPLSException) {return (AbstractPLSException) cause;} else {ExceptionEnum exceptionEnum = ExceptionEnum.getByClazz(cause.getClass());if(exceptionEnum!=null){return new PLSServiceException(exceptionEnum.getErrorCode());}return new PLSServiceException("", "", "系统未知异常");}}/*** 格式化异常* @param e AbstractPLSException* @return ResultVO 自定义返回体*/private ResultVO formatError(AbstractPLSException e) {return VoHelper.getErrorResult(e.getStateMsg());}private Response buildExceptionResponse(Response response) {return buildExceptionResponse(response.getException());}
}

完成上面的代码后,motan接口统一处理就完成了。

3.使用

1. 抛出异常
throw new PlsBizException(PlsBizErrorCode.P_YA0001);
2. motan门面类

异常不进行抓取 ,需要处理异常的地方进行抛出 throws Exception

没有统一处理前

@Override
public String addListing(String jsonParam) {LOGGER.info("新增listing接口被请求,请求参数jsonParam:{}", jsonParam);ResultVO resultVO = new ResultVO();try {//...resultVO = iPlsAliexpressListingService.addListing(data, operator);} catch (ValidatorParameterException vpe) {resultVO.setMsg(vpe.getMessage());resultVO.setState(ResponseCode.FAIL.getCode());} catch (WarningException e) {resultVO.setMsg(e.getMessage());resultVO.setState(ResponseCode.WARNING.getCode());LOGGER.error("AliExpress addListing 新增Listing  侵权检测警告,{} ", e.getMessage(), e);} catch (Exception e) {resultVO.setMsg(e.getMessage());resultVO.setState(ResponseCode.FAIL.getCode());LOGGER.error("新增listing接口异常", e);}return JSONUtils.toJSON(resultVO);
}

统一处理后

 @Overridepublic String addListing(String jsonParam)  throws Exception{LOGGER.info("新增listing接口被请求,请求参数jsonParam:{}", jsonParam);//..ResultVO resultVO = iPlsAliexpressListingService.addListing(data, operator);}

可以看到代码变得简洁了很多,而且异常的格式也得到规范。

} catch (Exception e) {resultVO.setMsg(e.getMessage());resultVO.setState(ResponseCode.FAIL.getCode());LOGGER.error("新增listing接口异常", e);
}
return JSONUtils.toJSON(resultVO);

}


统一处理后```java@Overridepublic String addListing(String jsonParam)  throws Exception{LOGGER.info("新增listing接口被请求,请求参数jsonParam:{}", jsonParam);//..ResultVO resultVO = iPlsAliexpressListingService.addListing(data, operator);}

可以看到代码变得简洁了很多,而且异常的格式也得到规范。

motan rpc 接口统一异常处理相关推荐

  1. dubbo接口统一异常处理的两种方式

    dubbo接口统一异常处理的两种方式 参考文章: (1)dubbo接口统一异常处理的两种方式 (2)https://www.cnblogs.com/zcz527/p/7655235.html 备忘一下 ...

  2. 在vue项目中:统一封装 Axios 接口与异常处理

    在vue项目中:统一封装 Axios 接口与异常处理 参考文章: (1)在vue项目中:统一封装 Axios 接口与异常处理 (2)https://www.cnblogs.com/itgezhu/p/ ...

  3. STS创建Spring Boot项目实战(Rest接口、数据库、用户认证、分布式Token JWT、Redis操作、日志和统一异常处理)

    STS创建Spring Boot项目实战(Rest接口.数据库.用户认证.分布式Token JWT.Redis操作.日志和统一异常处理) 1.项目创建 1.新建工程 2.选择打包方式,这边可以选择为打 ...

  4. SSM8==纯注解SSM项目:实现单表CRUD、事务、自定义异常和统一异常处理、RESTFUL风格接口、统一返回值格式(状态码、内容、消息)、JSON传参、axios、vue.js、elementUI

    环境:IDEA2021+JDK8+MAVEN3.8+TOMCAT7插件 前端:axios.vue.js.elementUI 后端:见POM.XML相关依赖,主要有数据库MySQL5.7 ,数据源Dru ...

  5. 设计RPC接口时,你有考虑过这些吗?

    RPC 框架的讨论一直是各个技术交流群中的热点话题,阿里的 dubbo,新浪微博的 motan,谷歌的 grpc,以及不久前蚂蚁金服开源的 sofa,都是比较出名的 RPC 框架.RPC 框架,或者一 ...

  6. ssm 异常捕获 统一处理_SSM 统一异常处理

    SSM 统一异常处理 spring创建中, 处理异常可以使用try-cache处理, 也可以使用spring提供的统一异常处理 在spring中, 统一处理异常有2中方式 注解方式 @Exceptio ...

  7. ssm 异常捕获 统一处理_SpringMVC 统一异常处理介绍及实战

    背景 什么是统一异常处理 目标 统一异常处理实战 用 Assert(断言) 替换 throw exception 定义统一异常处理器类 扩展 总结 <Java 2019 超神之路> < ...

  8. 使用Spring MVC统一异常处理实战

    原文:http://blog.csdn.net/ufo2910628/article/details/40399539 1 描述  在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处 ...

  9. trycatch抛出异常_Java生鲜电商平台架构中,如何统一异常处理及架构实战

    补充说明:本文讲得比较细,所以篇幅较长.请认真读完,希望读完后能对统一异常处理有一个清晰的认识. 背景 软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理各种异 ...

最新文章

  1. R语言读写二进制文件:WriteBin()、readBin()
  2. 性能优化技巧 - 内存关联计算
  3. Kali Linux常用服务配置教程启动DHCP服务
  4. Java并发教程–可调用,将来
  5. 为对象添加方法mothod
  6. Linux SD卡驱动开发(四) —— SD 控制器之真正的硬件操作
  7. 画面风格写实的飞鸽传书
  8. urllib库的学习-发起请求urlopen-下载资源urlretrleve
  9. 深信服环境SCSA环境遇到的问题(无法访问网站)
  10. python混合线性模型_Python中的多元线性混合效应模型
  11. LM358运放(比较器、跟随器)输出最高电压问题的探讨
  12. 1.54寸TFT ST7789液晶屏图片如何取模
  13. Windows 用 CMD 打开 WAMP5 的MySQL数据库
  14. [转载]班主任带着学生打副本 每周学习成绩就是DKP(这篇太雷人了,转载保持)...
  15. 《互联网人叹气图鉴》
  16. Bresenham快速画直线算法
  17. 微信小程序iconfont字体图标文件无法上传问题
  18. ubuntu下添加路径到PATH
  19. 金融行业的VC风险投资,PE私募股权,LP有限合伙人,GP普通合伙人
  20. 如何在中国制造网(made-in-china)上做生意

热门文章

  1. jp摩根的人都在学python么_摩根大通:不懂编程的人我们不要
  2. OSG、OSGEarth使用
  3. 深入理解硬盘的 Linux 分区
  4. 【业界偷懒】【Public】BZOJ题目一句话题解整理
  5. 微信jssdk开发 java_Java微信公众平台开发(十三)--微信JSSDK中Config配置
  6. matlab画3维meshgrid/plot3/mesh/surf的用法
  7. 第一类曲线、曲面积分计算公式
  8. 探索Java8——流(Stream)
  9. 阿里云移动研发平台体验报告
  10. [每日100问][2011-10-07]iphone开发笔记,今天你肿了么