This article is a follow-up to this article (https://www.cnblogs.com/Binhua-Liu/p/5577622.html), This article describes the protobuf of adding a layer of headers from the PROTOBUF in the Netty framework can only have a limited object. In Mushroom Street open source TEAMtalk, also added a header, according to the type of operation in the header, the corresponding logical processing operation.
Here is our configuration file for implementing the logic of Decodebody in Servercustomdecodehandler. Protobuf the generation of objects by reflection requires the use of the "Package $ class" form.
<?XML version= "1.0" encoding= "UTF-8"?><Decodetypes> <Decodetypetype= "Com.zywj.protobuf.out.imbase$messagecmdid"Val= "Cid_msg_data_value"class= "Com.zywj.protobuf.out.immessage$msgdata" /> <Decodetypetype= "Com.zywj.protobuf.out.imbase$othercmdid"Val= "Cid_other_heartbeat_value"class= "Com.zywj.protobuf.out.imother$heartbeat" /></Decodetypes>
The work of reading XML is placed in the server and declared as private static. Here is a map variable generated based on my own logic.
Private StaticMap parsexmldata (String xmlfilepath) {Saxreader reader=NewSaxreader (); Document Doc=NULL; Try{doc= Reader.read (NewFile (Xmlfilepath)); } Catch(documentexception e) {e.printstacktrace (); } Element Root=doc.getrootelement (); Map<String,Map> Map =NewHashmap<>(); for(Iterator i_action=root.elementiterator (); I_action.hasnext ();) {Element e_action=(Element) i_action.next (); Iterator it=E_action.attributeiterator (); Attribute Key=(Attribute) it.next (); String type=Key.getvalue (); Map<string, string> inner =NewHashmap<>(); while(It.hasnext ()) {Attribute Attribute=(Attribute) it.next (); Inner.put (Attribute.getname (), Attribute.getvalue ()); } map.put (type, inner); } returnmap; }
The work of Servercustomdecodehandler's decodebody is to generate objects from the data in the map by reflection, and it is necessary to determine if the current object's enum value is equal to CommandID, if found, The corresponding Protobuf object is generated.
PublicMessagelite Decodebody ( ShortCommandId,byte[] Array,intOffsetintLengththrowsException {Map<string, map> decodemap =Server.decodemap; for(Map.entry<string, map>Entry:decodeMap.entrySet ()) {Map<string, string> m =Decodemap.get (Entry.getkey ()); Class Clazz=Class.forName (Entry.getkey ()); Field F= Clazz.getfield (M.get ("Val")); if((int) F.get (clazz) = =commandId) {Class CLS= Class.forName (M.get ("Class")); Method Method= Cls.getmethod ("Getdefaultinstance"); Object obj= Method.invoke (CLS,NULL); Method= Cls.getmethod ("Getparserfortype"); Obj= Method.invoke (obj,NULL); return((parser<messagelite>obj). Parsefrom (array, offset, length); } } return NULL; }
Here, is not finished, because Serverhandler inside is passed in is the object MSG, so also use instanceof to determine if it is protobuf objects. So again it's an XML, and then reflection.
<?XML version= "1.0" encoding= "UTF-8"?><Msgtypes> <Msgtypetype= "Com.zywj.protobuf.out.immessage$msgdata"class= "Com.zywj.server.LogicHandler"Method= "Handlemsgdata" /> <Msgtypetype= "Com.zywj.protobuf.out.imother$heartbeat"class= "Com.zywj.server.LogicHandler"Method= "Handleheartbeat" /></Msgtypes>
The channelRead0 in Serverhanlder is changed into
@Override Public voidChannelRead0 (Channelhandlercontext ctx, Object msg)throwsException {Map<string, map> dispatchmap =Server.dispatchmap; for(Map.entry<string, map>Entry:dispatchMap.entrySet ()) {Class Clazz=Class.forName (Entry.getkey ()); if(Msg.getclass (). IsAssignableFrom (Clazz)) {Map<string, string> m =Dispatchmap.get (Entry.getkey ()); Class Clazzlogic= Class.forName (M.get ("Class")); Method Handle= Clazzlogic.getdeclaredmethod (M.get ("method"), Channelhandlercontext.class, Object.class); Handle.invoke (Clazzlogic.newinstance (), CTX, msg); Break; } } }
Severcustomencodehandler is the same way, not to repeat.
Here, we use reflection to put too much if...else in the above article ... To avoid it.
Finally, I think there will be too much reflection (cyclic reflection, Time complexity O (n)), and the amount of code actually does not decrease, just transferred to the XML, the biggest advantage is to reduce the coupling bar.
Netty + PROTOBUF uses reflection to implement multiple types of transmission