整理的内容

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. HDU-4690 EBCDIC 映射,模拟,沙茶

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4690 纯沙茶模拟题... //STATUS:C++_AC_93MS_228KB #include &l ...

  2. A Tour of Go Methods continued

    In fact, you can define a method on any type you define in your package, not just structs. You canno ...

  3. 简单dp-poj-2231-Moo Volume

    题目链接: http://poj.org/problem?id=2231 题目大意: 给n个位置,求所有位置到其他n-1个位置的距离总和. 解题思路: 简单dp. o(n^2)的时间复杂度会超.先对这 ...

  4. 高级C++开发工程师综合测试题(风林火山)

    题目要求:代码要求能够直接编译运行 1.       请实现一个函数:凑14:输入很多个整数(1<=数值<=13),任意两个数相加等于14就可以从数组中删除这两个数,求剩余数(按由小到大排 ...

  5. JQuery事件处理的注意事项

    1.jQuery 名称冲突 jQuery 使用 $ 符号作为 jQuery 的简介方式. 某些其他 JavaScript 库中的函数(比如 Prototype)同样使用 $ 符号. jQuery 使用 ...

  6. ASP.Net 使用SqlBulkCopy批量插入

    批量插入,以前我的做法是生成一堆insert into的sql语句,然后用程序一次值行,来实现. 今天看到了ASP.Net里可以使用DataTable,先将数据写入到DataTable中,然后使用Sq ...

  7. 使用JavaScript实现分页效果

    应公司需求,有时需要制作静态页面网站,而一旦涉及到文章的分页,实现起来非常麻烦,自己又刚入门,对js不是很熟悉,所以就拿来练练手. 首先页面结构如下,分别展示数据跟分页: <!DOCTYPE h ...

  8. 一些好用的nginx第三方模块

    一些好用的nginx第三方模块 转自;http://macken.iteye.com/blog/1963301  1.Development Kit https://github.com/simpl/ ...

  9. ThinkPHP CURD方法盘点:field方法

    ThinkPHP的CURD操作中有很多非常实用的方法,从这篇开始,我们会为大家一一介绍. 首先为大家介绍下field方法的用法.field属于模型的连贯操作方法之一,主要目的是标识要返回或者操作的字段 ...

  10. windows环境下搭建ffmpeg开发环境

           ffmpeg是一个开源.跨平台的程序库,能够使用在windows.linux等平台下,本文将简单解说windows环境下ffmpeg开发环境搭建过程,本人使用的操作系统为windows ...