motan rpc 接口统一异常处理

article/2025/9/11 4:38:32

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实现声明 c l a s s p a t h / M E T A − I N F / s e r v i c e s / {classpath}/META-INF/services/ classpath/METAINF/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);}

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


http://chatgpt.dhexx.cn/article/K2SpyqIx.shtml

相关文章

motan用户开发指南

目录 基本介绍 架构概述 模块概述 配置概述 使用Motan 工程依赖 处理调用异常 配置说明 协议与连接&#xff08;motan:protocol) 介绍 Motan协议 本地调用 注册中心与服务发现(motan:registry) 介绍 使用Consul作为注册中心 使用Zookeeper作为注册中心 不使用…

从motan看RPC框架设计

kris的文章开始 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决 从零开发一款RPC框架&#xff0c;说难也难说简单也简单。难的是你的设计将如何面对实际中的复杂应用场景&#xff1b;简单的是其思想可以仅仅浓缩成一行方法调用。motan是今年(2016年)新浪微博…

motan与zookeeper框架

新浪科技讯 2016年5月10日&#xff0c;微博方面宣布&#xff0c;支撑微博千亿调用的轻量级 RPC 框架 Motan 正式开源了。微博技术团队希望未来能有更多优秀的开源人入驻&#xff0c;并进一步完善优化。 搭建新浪RPC框架motan Demo&#xff1a;http://blog.csdn.net/linuu/arti…

java rpc motan_RPC框架motan使用

简介 motan是新浪微博开源的一套轻量级、方便使用的RPC框架 Hello World 使用的过程分为Server端和Client端&#xff0c;Server提供RCP的服务接口&#xff0c;Client端发起调用获取结果。 maven的pom文件配置 0.2.1 com.weibo motan-core ${motan.version} com.weibo motan-tra…

轻量级Rpc框架设计--motan源码解析一:框架介绍及框架使用初体验

一, 框架介绍 1.1 概况 motan是新浪微博开源出来的一套高性能、易于使用的分布式远程服务调用(RPC)框架。 1.2 功能 可以spring的配置方式与项目集成. 支持zookeeper服务发现组件, 实现集群环境下服务注册与发现. 保证高并发, 高负载场景下的稳定高性能, , 实现生产环境…

Motan原理、使用、JavaAPI简化、为什么使用Motan

前言&#xff0c;本文包括&#xff0c;rpc解释与为什么使用rpc、rpc性能对比、Motan依赖问题、Motan源码梳理、Motan功能、特点、使用。 主要中心&#xff1a;为什么使用Motan? 一、什么是RPC 官方解释&#xff1a;RPC&#xff08;Remote Procedure Call&#xff09;—远程…

jplayer自动播放

音乐网站的播放器一直都没有解决自动播放的问题&#xff0c;小哲说这样不行的&#xff0c;我也知道不可以这样&#xff0c;毕竟是自己提出要做的&#xff0c;所以要尽自己最大的能力去做好它&#xff01;本周末我一直都在围绕这个问题而研究。 我曾经想过在播放器初始化的时候…

JWPlayer

原文&#xff1a; http://www.cnblogs.com/yukui/archive/2009/03/12/1409469.html The JW MP3 Player (built with Adobes Flash) is the easiest way to add live music or podcasts to your website. It supports playback of a single MP3 file or an RSS, XSPF or ASX pla…

今天开始写些随笔,就从Jplayer开始吧

今天才开始用Jplayer&#xff0c;可能有点落伍了&#xff0c;但是看到网上千篇一律的使用说明&#xff0c;开始决定把自己的使用心得分享一下&#xff0c;废话不多说&#xff0c;开始吧。 Step1&#xff1a; 官网上有具体的搭建顺序&#xff0c;URL&#xff1a;http://www.jp…

关于播放器JPlayer的使用及遇到的问题

jPlayer是一个用于控制和播放mp3文件的jQuery插件。它在后台使用Flash来播放mp3文件&#xff0c;前台播放器外观完全可以使用XHML/CSS自定义。支持&#xff1a; 有一点比较好的是&#xff0c;在支持html5的浏览器上会使用html5的标签audio或者video&#xff0c;而不支持的浏览…

ijkplayer支持播放rtsp、jpeg、gif

ijkplayer版本&#xff1a;k.0.8.8 编译环境&#xff1a;Ubuntu 18.04.6 LTS 使用平台&#xff1a;android 支持rtsp播放 默认的ijkplayer并不支持rtsp流的播放&#xff0c;因为在编译ffmpeg的时候并没有开启rtsp的demuxer&#xff0c;所以在编译ffmpeg的时候需要开启rtsp的d…

【ijkplayer】介绍

【ijkplayer】介绍 0x1 系统架构 ijkplayer是由b站开源的播放器项目&#xff0c;底层基于ffmpeg, 支持Android和iOS。下面我们来简单介绍一下Android上的实现。 Android上的系统架构图如下。 下面分别对各个模块进行介绍&#xff1a; 0x11 ijkplayer-example app的实现&a…

一款简洁的 jplayer 音乐播放器完整版

一款简洁 jplayer 音乐播放器&#xff0c;做音乐站很漂亮&#xff0c;直接套用就好了。 效果图&#xff1a; 部分源代码&#xff1a; <div id"lei_jplayer"></div> <div id"jp_container_1"><div class"jp-controls">…

Ijkplayer Android介绍

Ijkplayer Android目录结构 Ijkplayer Android可以将该工程导入android studio进行编译&#xff0c;当它下载好需要的资源文件&#xff08;例如sdk build tool&#xff0c;gradle等&#xff09;就可以进行编译了&#xff0c;该工程的目录结构如下图所示: 链接库&#xff1a…

ijkplayer播放器

播放器系列 android播放器&#xff1a;MediaPlayer ExoPlayer ijkplayer_步基的博客-CSDN博客_mediacodec流程 一 概述 IJKPlayer是一款基于ffmpeg/ffplay的开源播放器&#xff0c;可支持rtmp/rtsp/hls等多种媒体协议&#xff0c;支持Android/IOS等移动平台。项目地址&#xff…

jplayer详解

下载官网&#xff1a;http://www.jplayer.org/ 当前版本&#xff1a;2.3.0 功能&#xff1a;视频播放&#xff08;可全屏&#xff09;、音乐播放 全部原教程&#xff0c;说明并不详细&#xff0c;要结合查看其网页源代码来学习&#xff1a;http://www.jplayer.org/latest/demos…

Javplayer 整合插件版下载使用

Javplayer - 马赛克去除工具 工作中去除图片模糊像素&#xff0c;还原高清图片Javplayer - 马赛克去除工具简介版本安装使用调整示例注意事项体验视频小结咨询 工作中去除图片模糊像素&#xff0c;还原高清图片 Javplayer - 马赛克去除工具简介 JavPlayer是一种视频播放器&am…

jPlayer使用详解

原文地址&#xff1a;http://blog.csdn.net/z295304557/article/details/17298889?_t_t_t0.39512087353182124 下载官网&#xff1a;http://www.jplayer.org/ 当前版本&#xff1a;2.3.0 功能&#xff1a;视频播放&#xff08;可全屏&#xff09;、音乐播放 全部原教程&#x…

jPlayer插件的使用

jPlayer插件的使用 2017年04月21日 11:03:19 JENIFURS 阅读数&#xff1a;3952 标签&#xff1a; jPlayer视频插件兼容bug 更多 个人分类&#xff1a; jQuery 版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/fuyujiaof/arti…

JPlayer播放器插件教程,JPlayer项目实战

JPlayer 播放器&#xff1a;基于HTML5/Flash的音频、视频播放器。项目预览&#xff1a;播放器插件预览jPlayer中文官方文档&#xff1a;官网功能强大&#xff0c;操作简便&#xff0c;支持换肤功能。引入JPlayer文件以及样式&#xff1a;<head><script type"text…