整理的内容
1.手动获取spring的ApplicationContext和bean对象
写一个工具类实现ApplicationContextAware接口
2.反射的知识整理
3.前后端协议交互的时使用命令号,可以方便调用后端的执行方法
定义一个对象:ActionDefine,表示消息编号与消息处理类的映射定义
package com.youxigu.dynasty2.core.flex; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import com.youxigu.dynasty2.util.StringUtils; import com.youxigu.wolf.net.codec.IAMF3Message; /** * 消息编号与消息处理类的映射定义 * * @author Administrator * */ public class ActionDefine { /** * 消息编号 */ private int cmd; /** * 消息处理类 */ private Object bean; /** * 消息处理类的处理方法 */ private String methodName; /** * 传入参数的类型 */ private Class<? extends IAMF3Message> inParmClass; /** * 返回参数的类型 */ private Class<? extends IAMF3Message> outParmClass; /** * 缓存Method实例,避免每次都查找Method */ private transient Method method; private transient Method prevMethod; public Method getMethod() { return method; } public void setMethod(Method method) { this.method = method; } public Method getPrevMethod() { return prevMethod; } public void setPrevMethod(Method prevMethod) { this.prevMethod = prevMethod; } public int getCmd() { return cmd; } public void setCmd(int cmd) { this.cmd = cmd; } public Object getBean() { return bean; } public void setBean(Object bean) { this.bean = bean; } public String getMethodName() { return methodName; } public void setMethodName(String methodName) { this.methodName = methodName; } public Class<? extends IAMF3Message> getInParmClass() { return inParmClass; } public void setInParmClass(Class<? extends IAMF3Message> inParmClass) { this.inParmClass = inParmClass; } public Class<? extends IAMF3Message> getOutParmClass() { return outParmClass; } public void setOutParmClass(Class<? extends IAMF3Message> outParmClass) { this.outParmClass = outParmClass; } }
spring配置文件中增加配置
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:flex="http://www.springframework.org/schema/flex" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd http://www.springframework.org/schema/flex http://www.springframework.org/schema/flex/spring-flex-1.0.xsd"> <!-- 11001命令代表要执行friendAction类中findUser方法--> <bean class="com.youxigu.dynasty2.core.flex.ActionDefine"> <property name="cmd" value="11001"/> <property name="bean" ref="friendAction"/> <property name="methodName" value="findUser"/> </bean> <!-- 申请好友-11002--> <bean class="com.youxigu.dynasty2.core.flex.ActionDefine"> <property name="cmd" value="11002"/> <property name="bean" ref="friendAction"/> <property name="methodName" value="appFriend"/> </bean> ...略 </beans>
手动初始化所有的actio定义,创建cmd和method的映射
实现类接口ApplicationContextAware 就要实现他的方法setApplicationContext(ApplicationContext ctx)
package com.youxigu.dynasty2.core.protobuf; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.TimeoutException; import org.apache.mina.core.session.IoSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import com.google.protobuf.Message; import com.manu.core.ServiceLocator; import com.youxigu.dynasty2.chat.EventMessage; import com.youxigu.dynasty2.chat.MessageFilter; import com.youxigu.dynasty2.chat.MessageFilter.FilterMessages; import com.youxigu.dynasty2.chat.client.IChatClientService; import com.youxigu.dynasty2.core.flex.ActionDefine; import com.youxigu.dynasty2.core.flex.amf.AMF3WolfService; import com.youxigu.dynasty2.core.flex.amf.IAMF3Action; import com.youxigu.dynasty2.user.service.IAccountService; import com.youxigu.dynasty2.util.BaseException; import com.youxigu.wolf.net.IInitListener; import com.youxigu.wolf.net.IWolfService; import com.youxigu.wolf.net.OnlineUserSessionManager; import com.youxigu.wolf.net.Response; import com.youxigu.wolf.net.ResultMgr; import com.youxigu.wolf.net.SocketContext; import com.youxigu.wolf.net.SyncWolfTask; import com.youxigu.wolf.net.UserSession; /** * 接收并处理所有Flex客户端的请求 * * @author Administrator * */ public class ProtobufWolfService implements IWolfService, IInitListener, ApplicationContextAware { public static Logger log = LoggerFactory.getLogger(AMF3WolfService.class); private Map<Integer, ActionDefine> actions = new HashMap<Integer, ActionDefine>(); private List<ActionDefine> actionDefines; public void setActionDefines(List<ActionDefine> actionDefines) { this.actionDefines = actionDefines; } @Override public void setApplicationContext(ApplicationContext ctx) throws BeansException { if (actionDefines == null) { actionDefines = new ArrayList<ActionDefine>(); while (ctx != null) {
//遍历所有的配置文件
//取出bean的类型为ActionDefine的所有bean Map<String, ActionDefine> maps = ctx.getBeansOfType(ActionDefine.class); if (maps.values() != null && maps.values().size() > 0) { actionDefines.addAll(maps.values()); } ctx = ctx.getParent(); } } if (actionDefines != null) { // 初始化ActionDefine
//声明方法的传入值类型数组,后面会强制修改 Class[] paramsType = { Object.class, Response.class }; for (ActionDefine ad : actionDefines) { int cmd = ad.getCmd();//命令号 if (actions.containsKey(cmd)) { throw new BaseException("重复的命令号:" + cmd); } if (ad.getSubActionIds() == null) {try {
//用方法名和传入值类型反射取到方法声明 Method m = ad.getBean().getClass().getDeclaredMethod(ad.getMethodName(), paramsType); ad.setMethod(m);//有了method声明就可以invoke来调用方法了 String beforeMethodName = ad.getPrevMethodName(); if (beforeMethodName != null && !"".equals(beforeMethodName)) { m = ad.getBean().getClass().getDeclaredMethod(beforeMethodName, paramsType); ad.setPrevMethod(m); } } catch (NoSuchMethodException e) { e.printStackTrace(); log.error("action mapping is error : cmd={}", cmd); } } actions.put(cmd, ad); } actionDefines.clear(); actionDefines = null; } } public void init() { } @Override public Object handleMessage(Response response, Object message) { if (message instanceof com.google.protobuf.Message) { com.google.protobuf.Message params = (com.google.protobuf.Message) message; try {
//用名称反射取得字段声明 Field cmdF = params.getClass().getDeclaredField("cmd_"); if(cmdF != null) { cmdF.setAccessible(true);
//用Filed取得字段值 int cmd_ = cmdF.getInt(params);
//取得缓存中方法声明 ActionDefine ad = actions.get(cmd_); Method m = null; int cmd = ad.getCmd(); if (actions != null) { ad = actions.get(cmd); if (ad != null) m = ad.getMethod(); } if (m == null) { throw new BaseException("错误的命令号:" + cmd); } //调用方法 Object retu_ = m.invoke(ad.getBean(), new Object[] { message, response }); // ........ } } catch (Exception e) { e.printStackTrace(); } } return null; } }