一:消息分类
消息按照因果关系分类,可以分为Request和Response,当然也有直接继承至Message的,表示我这个消息发出去后我就不care了。Request和Response是成对的,我发了一个Request,你必须回我一个对应的Response消息。
消息还可以按照类型分类,基本分为两大类,一般消息和Actor消息。Actor消息可以认为是战斗相关消息,战斗unit和玩家client之间发送的都是Actor消息,比如帧同步消息(AFrameMessage)就是一种ActorMessage,其他的都可以认为是一般消息,比如登陆,创角等。
Actor相关的消息在服务器间相互转发的时候,会被包装一下。想象一下,一个Client与GateServer之间的通信,消息里面是不用带玩家角色Id的,我们之间的Session对象就表明了我的身份。但是GateServe把这个消息转发给MapServer的时候,消息就得包装一下,带上UnitId的信息,这样MapServer收到这个消息后才知道是那个玩家发过来的。包装actor消息包括ActorRequest和ActorRPCRequest,AActorMessage不需要回复,就包装在ActorRequest中,而AActorRequest需要回复,包装在ActorRPCRequest中。所以ActorRequest和ActorRPCRequest包括他们的回复消息只在服务器之间传送Actor消息的时候用。
其实按照消息的路径,还可以把消息分为内部消息和外部消息,内部就是服务器内部之间发送的,外部则是负责服务器和客户端通信的。在ET中,有InnerMessage和OuterMessage两个文件,里面定义的消息就分别是内部和外部消息。只有Realm服务器和Gate服务器有NetOuterComponent,可以与客户端通信,其他服务器都只有NetInnerComponent,Realm服务器作为初始登陆服务器,负责分配Gate服务器给玩家,之后玩家都直接与Gate服务器通信,之后其他服务器都通过Gate服务器与玩家通信。
二:消息流程
这里面弄清了几个原则,基本就清楚了消息的处理原则:
1:Gate服务器既需要与客户端通信,也需要与其他服务器通信。所有同时拥有NetOuterComponent和NetInnerComponent。
2:Map服务器不直接与客户端通信,需要通过Gate服务器转发,所以只有NetInnerComponent。
3:客户端发送给Gate服务器的消息,都是通过NetOuterComponent走的,所以Actor消息都是AActorMessage或者AActorRequest类型(因为Gate服务器上接收消息的Session就表明了客户端的身份),而这些Actor消息是需要转发给Map服务器的,Gate服务器和每个Map服务器之间都只有一个Session(属于NetInnerComponent),所有Actor消息都通过这个Session发送,所以Actor消息在这里需要包装成ActorRequest或者ActorRpcRequest消息,带actorId,Map服务器接收到这个消息后通过actorId才知道交给哪个Actor处理。
4:Map服务器发送给Gate服务器的ActorRequest或者ActorRpcRequest消息,Gate服务器只需要把包装里面的AMessage发送给对应的客户端即可。
javax.ws.rs.ext.Providers 是JAX-RS 2.0定义的一种辅助接口,其实现类用于辅助REST框架完成过滤和读写拦截的功能,可以使用@Provider 注解标注这些类。Providers接口一共定义了四个方法,分别用来获取MessageBodyReader,MessageBodyWriter,ExceptionMapper,ContextResolver
Jersey 之所以支持那么多中响应实体的传输格式,是因为其底层实体Providers具备的对不同格式的处理能力。Jersey内部提供了丰富的MessageBodyReader和MessageBodyWriter 接口的实现类,用于处理不同格式的表述
如上图,请求流程中存在三种角色,分别是:用户,REST客户端和REST服务器,请求始于请求的发送,止于调用Resonse的readEntity()方法
(1).用户请求提交数据,客户端接收请求,进入第一个扩展点:客户端请求过滤器 ClientRequestFilter 的filter()方法
(2).请求处理过滤完毕后,流程进入第二个扩展点:客户端写拦截器WriterInterceptor实现类的aroundWriterTo() 方法,实现对客户端序列化操作的拦截
(3).客户端消息体写处理器MessageBodyWriter 执行序列化,流程从客户端过渡到服务器端
(4).服务器接收请求,流程进入第三个扩展点:服务器前置请求过滤器ContainerRequestFilter实现类 的filter()方法
(5).过滤器处理完毕后,服务器根据请求匹配资源方法,如果匹配到相应的资源方法,流程进入第四个扩展点:服务器后置请求过滤器ContainerRequestFilter 实现类 的filter() 方法
(6).后置请求过滤器处理完毕后,力促进入第五个扩展点:服务器读拦截器ReaderInterceptor实现类 的aroundReadFrom() 方法,拦截服务器端反序列化操作
(7).服务器消息体读处理器MessageBodyReader 完成对客户端数据流的反序列化,服务器执行匹配的资源方法
(8).REST请求资源的处理完毕后,流程进入第六个扩展点:服务器响应过滤器 ContainerResponseFilter 实现类 的filter() 方法
(9).过滤器处理完毕后,流程进入第七个扩展点:服务器写拦截器WriterInterceptor实现类 的aroundWriterTo() 方法,实现对服务器端序列化到客户端这个操作的拦截
(10).服务器消息体写处理器MessageBodyWriter 执行序列化,流程返回到客户端一侧
(11).客户端接收响应,流程进入第八个扩展点:客户端响应过滤器ClientResponseFilter 实现类 的filter() 方法
(12).过滤处理完毕后,客户端响应实例response 返回到用户一侧,用户执行response.readEntity(),流程进入第九个扩展点:客户端拦截器ReaderInterceptor实现类 的aroundReadFrom() 方法,对客户端反序列化进行拦截
(13).客服端消息体读处理器MessageBodyReader 执行反序列化,将Java类型的对象最终作为readENtity()方法的返回值
JAX-RS-2.0定义的4种过滤器扩展点接口,供开发者实现其业务逻辑,按请求处理流程的先后顺序为:客户端请求过滤器(ClientRequestFilter) ------->服务端请求过滤器(ContainerRequestFilter)-------->服务端响应过滤器(ContainerResponseFilter)——>客户端响应过滤器(ClientResponseFilter)
ClientRequestFilter
ClientResponseFilter
ContainerRequestFilter
ContainerResponseFilter
Jersey 内部实现了几个典型应用的拦截器,他们是成对出现的
ReaderInterceptor
WriterInterceptor
编码解码拦截器(ContentEncoder)
优先级的定义使用注解 @Priority ,优先级的值是一个整数值,对于ContainerReauest,PreMatchContainerRequest,ClientRequest 和读写拦截器 采用升序策略,数值越小,优先级越高;对于ContainerResponse和ClientResponse采用降序策略,数值越大,优先级越高
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)