整理的内容

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;
}
}

通过spring来配置某个命令号和执行方法之间的映射的更多相关文章

  1. 使用Spring PropertyPlaceholderConfigurer 配置中文出现乱码的解决方法

    在使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 读取配置文件时,发现对于中文的处理会出现乱码现象,比 ...

  2. 记录一个 spring cloud 配置中心的坑,命令行端口参数无效,被覆盖,编码集问题无法读取文件等.

    spring cloud 配置中心 结合GIT , 可以运行时更新配置文件.发送指令让应用重新读取配置文件. 最近在测试服务器实现了一套,结果CPU 实用率暴增,使用docker compose启动 ...

  3. Spring Boot 配置文件和命令行配置

    Spring Boot 属于约定大于配置,就是说 Spring Boot 推荐不做配置,很多都是默认配置,但如果想要配置系统,使得软件符合业务定义,Spring Boot 可以通过多种方式进行配置. ...

  4. 在Spring中配置SQL server 2000

    前言 Lz主要目的是在Spring中配置SQL server 2000数据库,但实现目的的过程中参差着许多SQL server 2000的知识,也包罗在本文记载下来!(Lz为什么要去搞sql serv ...

  5. Tomcat配置和Spring MVC配置

    Tomcat启动时,先找系统变量CATALINA_BASE,如果没有,则找CATALINA_HOME.然后找这个变量所指的目录下的conf文件夹,从中读取配置文件.最重要的配置文件:server.xm ...

  6. spring cloud 配置纲要Properties

    名称 默认 描述 encrypt.fail-on-error true 标记说,如果存在加密或解密错误,进程将失败. encrypt.key   对称密钥.作为一个更强大的替代方案,考虑使用密钥库. ...

  7. 2、Spring Boot配置

    1.配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoo ...

  8. Spring Boot -- 配置切换指南

    一般在一个项目中,总是会有好多个环境.比如: 开发环境 -> 测试环境 -> 预发布环境 -> 生产环境 每个环境上的配置文件总是不一样的,甚至开发环境中每个开发者的环境可能也会有一 ...

  9. spring 定时任务配置

    1.(易)如何在spring中配置定时任务? spring的定时任务配置分为三个步骤: 1.定义任务 2.任务执行策略配置 3.启动任务 (程序中一般我们都是到过写的,直观些) 1.定义任务 < ...

随机推荐

  1. 检测是否安装了 .NET Framework 3.5

    此脚本是为 Internet Explorer 设计的.    其他浏览器可能在 UserAgent 字符串中不包含 .NET CLR 信息. <HTML> <HEAD> &l ...

  2. ubuntu 13.04下sublime text 3使用中文输入法

    主要思路参考 http://blog.yanwen.org/archives/1955.html libsublime-imfix.so 这个库自己编译和从他这下载的 md5一样.可以不用编译了.直接 ...

  3. whu 1464 deal with numbers

    WHU 1464  deal with numbers 题意: 给你一串数字,对着串数字有三项操作: Minus a,b,c:对区间[a,b]总的每个数都减c. Division a,b,c:对区间[ ...

  4. MongoDB介绍及下载与安装

    MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型.M ...

  5. Reactive native 项目创建失败如何处理

    首先感谢党的英明决策. 一开始我总觉得Awesomeproject这个名字是固定的,和我有同感的同学请举手. 其实我们可以起任意的名字,执行native react init碰到的最大的问题是 npm ...

  6. Android自定义下拉刷新

    网上的下拉刷新功能很多,不过基本上都是隐藏header的,而项目里面需要只隐藏部分的header,类似QQ好友动态的效果,修改了一些现有的,最后有很多问题,所以就自己自定义了一个,逻辑也很简单,首先就 ...

  7. iphone 3G\3GS 超详细拆机教程

    更为直观的iphone视频拆机教程: http://bbs.app111.com/thread-243147-1-1.html 第一步: 准备好所需工具 iphone一台....吸盘一个..屏幕布一块 ...

  8. c# 泛型List的定义、作用、用法

    定义:List<T>类表示可通过索引访问的对象的强类型列表,提供用于对列表进行搜索.排序和操作的方法. 作用: 泛型最常见的用途是泛型集合 我们在创建列表类时,列表项的数据类型可能是int ...

  9. ECSHOP在线手册布局参考图--文章详情页 article.dwt

        A.购物车 1,设置方法 程序自动读取购物车的商品数量 2,代码相关 cart.lbi 中 {insert_scripts files='transport.js'} <div clas ...

  10. NSTimer、 NSTask、 NSThread 和 NSRunloop 之间的区别

    NSTimer是一个计时器对象,方法调用在对未来的选择对象. NSThread是一个线程类. 也就是创建一个线程. NSTask类是一个过程,一种方式运行程序从您的其他程序. NSOperation是 ...