rop学习(三)

上一节讲解了rop如何进行参数的传递,以及返回。本章节讲解rop如何进行应用的授权访问以及验证 
当用户需要访问某个应用系统前,应用系统一般都需要对该用户进行身份认证。常见的身份认证方法是让用户输入“用户/密码” ,当通过验证后,允许进入系统,否则阻止用户登录系统和应用系统类似,服务开放平台也需要对接入的应用进行身份认证,以确保服务只向合法授权的客户端应用开放。一般的做法是:服务开放平台通过一个应用申请流程向通过 
审核的开发者分配一个唯一的应用键和应用密钥(即 appKey/secret) 。应用键是公开的,而应用密钥是保密的,只有开发者自己知道。 
开发者开发的应用在访问开放平台的服务时, 都必须带上这个 appKey, 以亮明自己的身份。此外,还必须通过应用密钥对请求数据进行签名,开放平台通过验证服务请求的签名判断客户端应用的合法性。也就是说,开放平台通过 appKey/secret 的机制对应用进行身份认证。 
3.2 应用键/密钥管理器 
由于 Rop 需要在服务端采用相同的算法计算请求参数的签名, 并和客户端传送过来的 
签名进行比较,如果两者相等,便认为当前交互的客户端是合法的客户端,反之则认为是 
一个非法的客户端。 
因此,服务端必须知道应用键及其应用密钥的信息,这样才能顺利完成服务端签名验 
证的工作, Rop 通过 com.rop.security.AppSecretManager 接口访问应用键/密钥。 您可以采用 
适合的方式保存应用键/密钥,如保存在数据库、LDAP、文件系统等地方,然后编写一个 
访问应用键/密钥的 AppSecretManager 实现类就可以了。 
AppSecretManager 拥有两个接口方法: 
 boolean isValidAppKey(String appKey):判断 appKey 是否是合法的应用键; 
 String getSecret(String appKey):根据 appKey 获取对应的应用密钥。 
Rop 默 认 提 供 了 一 个 基 于 文 件 存 储 的 FileBaseAppSecretManager 实 现 类 , 
FileBaseAppSecretManager 默认使用读取类路径下的 rop.appSecret.properties 属性文件,获 
取应用键/密钥,属性文件中应用键/密钥采用如下方式保存: 
00001=abcdeabcdeabcdeabcdeabcde 
3 应用授权及验证 
320 
00002=abcdeabcdeabcdeabcdeaaaaa 
属性名对应应用键,属性值对应应用密钥。如果属性文件放置在其它地方,则可以通 
过 appSecretFile 属性指定位置,appSecretFile 支持“classpath:”等 Spring 资源类型的前缀。 
由于大型服务平台一般是分布式的, 所以将应用键/密钥保存在系统文件中并不是个好 
主意。如果开发者希望提供自定义的 AppSecretManager,可通过的 
app-secret-manager 属性进行配置:

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>rop:annotation<span class="hljs-attribute" style="box-sizing: border-box;">-driven</span> app<span class="hljs-attribute" style="box-sizing: border-box;">-secret</span><span class="hljs-attribute" style="box-sizing: border-box;">-manager</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"appSecretManager"</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">/</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span>
<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>bean id<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"appSecretManager"</span> class<span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"com.rop.sample.SampleAppSecretManager"</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">/</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

这样,Rop 就会使用 SampleAppSecretManager 取代默认 FileBaseAppSecretManager 进 
行应用键/密钥的读取工作了。 
3.3 签名算法 
Rop 的签名算法直接参考了 TOP 的签名算法,该签名算法描述如下: 
(1) 所有请求参数按参数名升序排序; 
(2) 按 请 求 参 数 名 及 参 数 值 相 互 连 接 组 成 一 个 字 符 串 :

<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">paramName1</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">paramValue1</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">paramName2</span>></span><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">paramValue2</span>></span>…;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

(3) 将应用密钥分别添加到以上请求参数串的头部和尾部:< 请求参数字符 
串 >; 
(4) 对该字符串进行 SHA1 运算,得到一个二进制数组; 
(5) 将该二进制数组转换为十六进制的字符串,该字符串即是这些请求参数对应的签 
名; 
(6) 该签名值使用 sign 系统级参数一起和其它请求参数一起发送给服务开放平台。 
假设,user.create 的服务有 3 个业务级参数,分别为 userName、age 及 sex。这些业务 
级参数和系统级参数的值如下表所示: 
这里写图片描述
根据 Rop 的签名算法,首先按字母顺序将所有参数名和参数值拼装成一个字符串: 
age24appKey000001formatxmllocalezh_CNmethoduser.createsessionIdAAAAsex1userNameto 
msonv1.0 
假设,appKey 为 000001 的 secret(应用密钥)是“abcdef” ,则将“abcdef”分别添加 
到以上请求参数串的头部和尾部,得到: 
abcdefage24appKey000001formatxmllocalezh_CNmethoduser.createsessionIdAAAAsex1userN 
ametomsonv1.0abcdef 
对以上字符串进行 SHA1 签名运算,将签名值转换为十六进制的编码串,得到: 
8625FD7EEAE1E68203B48C64DE495792BF59E833 
最后,客户端即可使用如下的 URL 请求串对 user.create 服务方法发起请求: 
http:///?appKey=000001&method=user.create&… 
&sign=8625FD7EEAE1E68203B48C64DE495792BF59E833 
3.4 签名功能控制 
默认情况下,Rop 会对每个服务请求进行签名验证,如果签名验证报错,将直接驳回 
请求并回报相应的错误信息。Rop 允许服务平台开发者开启或关闭签名验证的功能,Rop 
提供了 3 个级别的控制: 
 平台级:开启或关闭服务平台所有服务的签名验证功能; 
 服务级:在平台级签名验证功能开启的情况下,可以关闭某个具体服务的签名验 
证; 
 参数级:在 10.4.3 小节中,我们知道 Rop 的签名算法要求把所有的参数拼装成一 
个字符串,如果有些参数值很大(如上传文件的文件内容) ,签名算法将需要构 
造一个很大的字符串,占用很大的内存。从安全上来说,仅需对一些关键的参数 
进行签名就可以了,并非一定要对所有的参数进行签名。有鉴于此,Rop 在服务 
签名时允许忽略某些参数,提供参数级的签名控制。 
平台级控制 
通过《rop:annotation-driven/》的 sign-enable 属性即可开启或关闭服务平台签名验证功 
能:

<code class="hljs lasso has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;"><</span>rop:annotation<span class="hljs-attribute" style="box-sizing: border-box;">-driven</span> sign<span class="hljs-attribute" style="box-sizing: border-box;">-enable</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">=</span><span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"false"</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">/</span><span class="hljs-subst" style="color: rgb(0, 0, 0); box-sizing: border-box;">></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li></ul>

我们强烈建议在生产环境下开启服务签名验证的功能,以保证服务平台的安全性,免 
受恶意客户终端的攻击。 
服务级控制 
在平台级签名功能开启的情况下,Rop 还允许关闭某个服务的签名验证功能。通过将 
@ServiceMethod 的 ignoreSign 属性设置为 IgnoreSignType.YES 即可:

<code class="hljs vbscript has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">@ServiceMethod(method = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"user.add"</span>, version = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"5.0"</span>, ignoreSign = IgnoreSignType.YES)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> Object addUser5(CreateUserRequest <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">request</span>) {
CreateUserResponse <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">response</span> = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> CreateUserResponse();
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">response</span>.setCreateTime(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"20120101010102"</span>);
<span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">response</span>.setUserId(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"4"</span>);
return <span class="hljs-built_in" style="color: rgb(102, 0, 102); box-sizing: border-box;">response</span>;</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

4 服务会话管理 
这样,客户端在访问 user.add#5.0 的服务方法时,就不必提供请求参数的签名信息了。 
参数级控制 
在定义服务方法的 RopRequest 类时,只要在 RopRequest 的某些属性上标注了 
@IgnoreSign, 这些属性所对应的请求参数就可以排除在签名参数列表之外了。 来看一个例public class LogonRequest extends AbstractRopRequest{ 
@Pattern(regexp = “\w{4,30}”) 
private String userName; 
@IgnoreSign 
@Pattern(regexp = “\w{6,30}”) 
private String password; 
… 
}onRequest 的 password 属性所对应的请求参数将不会纳入到签名算法的参数列表 
中。使用这种办法,可以在具体的 RopRequest 类中将某些属性对应的请求参数排除在签 
名算法之外。 
如果希望某一类型的属性统一忽略签名,有没有简单的方法呢?Rop 提供了一种非常 
便捷的方法,即在属性类定义处使用@IgnoreSign 注解即可。如用于保存上传文件的 
UploadFile 类就标注了@IgnoreSign 注解:

<code class="hljs cs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">@IgnoreSign
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> UploadFile {
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> String fileType;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">private</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">byte</span>[] content;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

这样, UploadFile作为任何RopRequest类的属性都将排除在签名算法的参数列表之外。

9 拦截器及事件体系 
9.1 拦截器 
服务请求在通过 SecurityManager 的安全检查后,Rop 将依次执行 com.rop.Interceptor 
拦截器的 beforeService()方法,一旦某个拦截器通过 RopRequestContext#setRopResponse() 
设置了一个响应对象, Rop 将终止执行链直接返回响应。 在目标服务方法执行成功后, Rop 
再依次执行这些拦截器的 beforeResponse()方法。其调用流程在图 8 中说明: 
这里写图片描述 
通过上图, 我们可以发现 Rop 的拦截器架构是完全参考了 Spring MVC 的拦截器体系 
设计的。我们来看一下 com.rop.Interceptor 有哪些接口方法: 
 void beforeService(RopRequestContext ropRequestContext): 在调用目标服务方法之 
前调用,如果在该方法中,通过 RopRequestContext#setRopResponse()设置了响应 
对象,Rop 将中断执行链的执行直接返回响应; 
 void beforeResponse(RopRequestContext ropRequestContext): 在调用完目标服务方 
法后,执行该拦截器方法; 
 boolean isMatch(RopRequestContext ropRequestContext): 可以通过该方法指定拦截 
器的匹配服务方法,只有该方法返回 true 时,拦截器才会实施拦截; 
 int getOrder():指定拦截器的先后顺序。 
rop-sample 中定义了一个 ReservedUserNameInterceptor 拦截器,来看一下它的代码:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">package</span> com.rop.sample;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.rop.AbstractInterceptor;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.rop.RopRequestContext;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> com.rop.sample.response.InterceptorResponse;
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">import</span> org.springframework.stereotype.Component;
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Component</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ReservedUserNameInterceptor</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">extends</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">AbstractInterceptor</span> {</span>
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">beforeService</span>(RopRequestContext ropRequestContext) { ①
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"jhonson"</span>.equals(ropRequestContext.getParamValue(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"userName"</span>))) {
InterceptorResponse response = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> InterceptorResponse();
response.setTestField(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"the userName can't be jhonson!"</span>);
ropRequestContext.setRopResponse(response);
}
}
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">beforeResponse</span>(RopRequestContext ropRequestContext) {
}
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> <span class="hljs-title" style="box-sizing: border-box;">isMatch</span>(RopRequestContext ropRequestContext) {②
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"user.add"</span>.equals(ropRequestContext.getMethod());
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li></ul>

ReservedUserNameInterceptor 的作用是确保调用“user.add”的服务时,新增用户的 
userName 不使用到预留的用户名。该拦截器通过 isMatch()限定拦截的目标,这里,仅对 
user.add 的服务实施拦截。 
在开发出拦截器后,还必须将拦截器注册到 Rop 中,这样拦截器才能工作。Rop 为注 
册拦截器提供了专门的 Schema:

<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rop:interceptors</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">bean</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">class</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.rop.sample.ReservedUserNameInterceptor"</span>/></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rop:interceptors</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

在《rop:interceptors/》中可以注册任意多个拦截器。

9.2 事件及监听 
Rop 框架拥有一个完成的事件体系:包括框架级事件和服务级事件。框架级事件包括 
框架启动后事件(AfterStartedRopEvent)及框架关闭前事件(PreCloseRopEvent) 。而服务 
级 事 件 包 括 服 务 执 行 前 事 件 ( PreDoServiceEvent ) 和 服 务 执 行 后 事 件 
(AfterDoServiceEvent) 。 
一般情况下,每个事件都要对应一个自己的监听器,但是 Spring 的事件体系颠覆了这 
种笨拙的设计模式,它只定义了一个监听器接口,通过泛型指定监听不同的事件。Rop 传 
承了 Spring 这一优秀的监听器设计理念,定义了

RopEventListenpublic interface RopEventListener extends EventListener { 
void onRopEvent(E ropEvent); 
int getOrder(); 
}

通过泛型 E 指定需要监听的事件类型就可以了, getOrder()接口方法指定 
监听器的执行顺序,序号越小越先执行。下面是 rop-sample 中的一个具体

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;">package <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rop</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.sampimport</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rop</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.RopRequest</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rop</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.RopRequestContext</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rop</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.event</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.PreDoServiceEvent</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rop</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.event</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.RopEventListener</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
import <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">com</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.rop</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.marshaller</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.MessageMarshallerUtils</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
public class SamplePreDoServiceEventListener
implements RopEventListener<PreDoServiceEvent> {①
@Override
public void onRopEvent(PreDoServiceEvent ropEvent) {
RopRequestContext ropRequestContext = ropEvent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getRopRequestContext</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
if(ropRequestContext != null && ropRequestContext<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getRopRequest</span>() != null){
RopRequest ropRequest = ropRequestContext<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getRopRequest</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
String message = MessageMarshallerUtils<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getMessage</span>(ropRequest,
ropRequestContext<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getMessageFormat</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
System<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.out</span><span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.println</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"message("</span>+ropEvent<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getServiceBeginTime</span>()+<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">")"</span>+message)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
}
}
@Override
public int getOrder() {
return <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span><span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
}
},</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li></ul>

事件监听器也必须注册到 Rop 中才会生效,其配置片断如下所示:

<code class="hljs xml has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rop:listeners</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">bean</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">class</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.rop.sample.SamplePostInitializeEventListener"</span>/></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">bean</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">class</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.rop.sample.SamplePreDoServiceEventListener"</span>/></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">bean</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">class</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.rop.sample.SampleAfterDoServiceEventListener"</span>/></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">rop:listeners</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

以上配置片断一共注册了 3 个事件监听器,它们分别监听不同的事件。如果多个监听 
器监听同一个事件,监听器的执行顺序由监听器的 getOrder()决定 。 
Rop 采用异步的方式执行事件监听,服务执行的线程和事件监听执行线程是两个不同 
的线程,也就是说,事件监听器的执行不会影响服务方法的执行。所以您可以开发一个监 
听 AfterDoServiceEvent 事件的监听器,记录每个请求/响应报文的日志,由于事件监听器 
异步运行,它不会影响正常服务执行的效率。 
值得注意的是,Rop 的拦截器是工作于服务执行线程中的,拦截器的执行效率会直接 
影响到服务执行的效率,因此,不宜在拦截器中做太多的事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值