博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
motan rpc 接口统一异常处理
阅读量:2061 次
发布时间:2019-04-29

本文共 12341 字,大约阅读时间需要 41 分钟。

1.hello word 一个Motan扩展

大概需要下面的三点:

  1. 实现SPI扩展点接口

    package com.weibo.api.motan.filter;@Spipublic interface Filter {
    Response filter(Caller
    caller, Request request);}

业务代码实现Filter

public class PlsProviderExceptionFilter implements Filter {
@Override public 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; } @Override public String getCode() {
return code; } @Override public String getName() {
return name; } @Override public 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
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); @Override public 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

没有统一处理前

@Overridepublic 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);}

统一处理后

@Override    public 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 @Override    public String addListing(String jsonParam)  throws Exception{         LOGGER.info("新增listing接口被请求,请求参数jsonParam:{}", jsonParam);    	//..        ResultVO resultVO = iPlsAliexpressListingService.addListing(data, operator);    }

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

转载地址:http://qzmlf.baihongyu.com/

你可能感兴趣的文章
windows下VS2015使用MSVC编译FFmpeg库
查看>>
windows下VS使用FFmpeg被声明为已否决的解决方案
查看>>
Win7 x64环境下Python3.6安装使用提示丢失api-ms-win-crt-runtimel1-1-0.dll
查看>>
c++ Lambda函数
查看>>
c++仿函数
查看>>
C++ STL bind1st和bind2nd
查看>>
windows下Python安装requests
查看>>
目的:解决Ubuntu 使用gedit出现No protocol specified (gedit:14333):
查看>>
解决Ceph集群Mon和OSD网络变更或者ip(主要是mon)变换后,集群不能正常工作问题
查看>>
Python 格式化打印json数据(展开状态)
查看>>
解决windows下libcurl中curl_formadd()的CURLFORM_FILENAME使用中文导致post失败的问题
查看>>
Centos7 安装curl(openssl)和libxml2
查看>>
Centos7 离线安装RabbitMQ,并配置集群
查看>>
Centos7 or Other Linux RPM包查询下载
查看>>
运行springboot项目出现:Type javax.xml.bind.JAXBContext not present
查看>>
Java中多线程向mysql插入同一条数据冲突问题
查看>>
Idea Maven项目使用jar包,添加到本地库使用
查看>>
FastDFS集群架构配置搭建(转载)
查看>>
HTM+CSS实现立方体图片旋转展示效果
查看>>
FFmpeg 命令操作音视频
查看>>