通过spring来配置某个命令号和执行方法之间的映射

整理的内容

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; } }
原文地址:https://www.cnblogs.com/dagangzi/p/4760233.html