拦截器只适用于非 HTTP 类型服务。
mobilegw-unify-spi-adapter.jar
实际上是通过 Java 的反射调用业务方法,即OperatioinType
所指定的方法。在方法调用的过程中,业务方可以实现 SPI 包中定义的拦截器,从而实现扩展。
网关的 SPI 包定义了两个拦截器:AbstractMobileServiceInterceptor
抽象类和 MobileServiceInterceptor
接口。
MobileServiceInterceptor
主要提供了四个方法,分别是 beforeInvoke
、afterInvoke
(入参为业务返回的 Object)、afterInvoke
(入参为 Object 转成的 JSON string)、throwsInvoke
,getOrder
。
如上图所示,拦截器主要在以下几个点进行拦截:
方法调用前:即 beforeInvoke
方法,该方法有返回值。一旦该方法的返回值不为空,那么网关认定拦截成功,将会跳过剩余拦截器的 beforeInvoke
方法,同时跳过调用业务方的方法,直接进入拦截器的 afterInvoke
方法。
方法调用后: 即 afterInvoke
方法。afterInvoke
有两种,一种入参是Object,即业务方返回的对象,该方法没有返回值,所有的拦截器的该方法都会执行;另一种入参是JSON string,该方法可以改变传入的 JSON 数据并返回。一旦返回值不为空,那么网关认定拦截成功,后续的拦截器将被忽略。
方法出现异常:即 throwsInvoke
方法。该方法没有返回值,所有拦截器的该方法都会被执行。在业务方出现异常时会被调用。
MobileServiceInterceptor
继承了框架的 Ordered
接口,因此,业务方实现的拦截器还可以通过实现 getOrder
方法指定执行顺序,设置的数值越小,执行的优先级越高;设置的数值越大,执行的优先级越低。
编码自己的拦截器类,继承 AbstractMobileServiceInterceptor
类,或者实现MobileServiceInterceptor
接口。
public class MyInterceptor implements MobileServiceInterceptor {
/*
参数说明
method:即业务方的方法(@OperatioinType 定义的方法)
args: 一个对象数组,即业务方方法的传入参数,传入参数个数即等于数组大小。
使用时业务方根据需要进行类型转换。
bean: 即业务方的接口实例。
返回值说明:
Object:可以在拦截器中返回数据,一旦返回值不为空,则网关认为已被拦截,就不会再调用业务方法
同时,直接跳过其他拦截器的 beforeInvoke 方法,执行拦截器中的 afterInvoke 方法。
*/
@Override
public Object beforeInvoke(Method method, Object[] args, Object target) {
//Do Something
return null;
}
/*
*参数说明
*returnValue: 业务方法返回的对象
* 其它参数同上
*/
@Override
public void afterInvoke(Object returnValue, Method method, Object[] args, Object target) {
//注意:这里入参是业务方返回的 Object
}
@Override
public String afterInvoke(String returnJsonValue, Method method, Object[] args, Object target) {
//注意:这里入参是由业务方返回的 object,转换而成的 JSON 格式的 string
//可以返回新的 JSON 数据
return null;
}
@Override
public void throwsInvoke(Throwable t, Method method, Object[] args, Object target) {
}
@Override
public int getOrder() {
//最高级(数值最小)和最低级(数值最大)。
return 0;
}
}
发布实现的类 MyInterceptor
,成为 Bean。
@service
。
@service
public class MyInterceptor implements MobileServiceInterceptor{}
xml
文件声明。
<bean id="myInterceptor" class="com.xxx.xxx.MyInterceptor"/>
MobileRpcHolder
是 mobilegw-unify-spi-adapter.jar
中提供的一个静态辅助类,该类定义了一个请求过程中的相关信息,最主要的定义如下:
Map<String, String> session 保存请求的 session
Map<String, String> header 保存请求的头部相关信息
Map<String, String> context 保存网关调用的上下文信息
String operationType 保存此次请求的 operationType
在业务方的服务(即 OperationType
)被调用之前,SPI 服务会根据网关转发的请求 MobileRpcRequest
去设置 MobileRpcHolder
这些信息。在调用业务方服务之后这些信息会被清除。
MobileRpcHolder
的生命周期为整个服务的调用过程,调用后清除。
业务方也可以根据需要去设置这些信息,这些信息会在调用业务的服务过程中一直存在,在调用过程中业务服务可以获取这些信息。具体的设置可以通过拦截器,在方法调用前后动态地修改 MobileRpcHolder
中保存的信息。
以下通过例子说明 MobileRpcHolder
如何使用。
这里以修改和获取 session 为例。
修改 session。
创建拦截器,具体过程看上面的拦截器例子。以下以在方法调用前为例:
@Override
public Object beforeInvoke(Method method, Object[] args, Object target) {
Map<String, String> session = MobileRpcHolder.getSession();
session.put("key_test", "value_test");
MobileRpcHolder.setSession(session);
}
这样就能修改 MobileRpcHolder
中的 session 信息。
获取 session。业务方在自己定义的服务中可以获取 session 信息。
@OperationType("com.alipay.account.query")
public String mock2(String s) {
Map<String, String> session = MobileRpcHolder.getSession();
}
其他信息(如 header、context)的修改和获取跟上面的一样。
// 获取 header 所有信息
Map<String,String> headers = MobileRpcHolder.getHeaders();
// 这里上下文信息指的是请求中的上下文信息
Map<String,String> context = MobileRpcHolder.getRequestCtx();
// 获取 OperationType
String opt = MobileRpcHolder.getOperationType();
网关有自己的一套错误码规范。详见 网关结果码说明。
需要注意 BizException 6666
,此错误是业务方出现异常后,网关会抛出的异常。
如果业务方想在具体出错时,返回其他错误码的需求。业务方可以通过抛出 RpcException(ResultEnum resultCode)
来控制 RPC 层的错误,比如 resultCode=1001
,会返回给客户端没有权限访问。
@Override
public String mock2(String s) throws RpcException {
try{
test();
}catch (Exception e){
throw new RpcException(IllegalArgument);
}
return "11111111";
}
如果业务方想使用自定义错误码,那么在调用业务方法时不能往外抛异常。
业务方法只要出现异常,就会返回状态码 6666。同时客户端收到该状态码,即认为服务出错,不会去解析业务返回的数据。客户端只有在接收到 1000 状态码时,才会去解析返回的数据。
因此,具体做法是,服务端和客户端约定好具体的错误码,然后在调用业务方法时 catch 掉所有的异常,将自定义错误码放在返回的数据中。这样业务就算出异常,网关也会返回 1000 成功。同时客户端去解析返回的数据,提取自定义错误码。
在文档使用中是否遇到以下问题
更多建议
匿名提交