通过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;
}
}
通过spring来配置某个命令号和执行方法之间的映射的更多相关文章
- 使用Spring PropertyPlaceholderConfigurer 配置中文出现乱码的解决方法
在使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer 读取配置文件时,发现对于中文的处理会出现乱码现象,比 ...
- 记录一个 spring cloud 配置中心的坑,命令行端口参数无效,被覆盖,编码集问题无法读取文件等.
spring cloud 配置中心 结合GIT , 可以运行时更新配置文件.发送指令让应用重新读取配置文件. 最近在测试服务器实现了一套,结果CPU 实用率暴增,使用docker compose启动 ...
- Spring Boot 配置文件和命令行配置
Spring Boot 属于约定大于配置,就是说 Spring Boot 推荐不做配置,很多都是默认配置,但如果想要配置系统,使得软件符合业务定义,Spring Boot 可以通过多种方式进行配置. ...
- 在Spring中配置SQL server 2000
前言 Lz主要目的是在Spring中配置SQL server 2000数据库,但实现目的的过程中参差着许多SQL server 2000的知识,也包罗在本文记载下来!(Lz为什么要去搞sql serv ...
- Tomcat配置和Spring MVC配置
Tomcat启动时,先找系统变量CATALINA_BASE,如果没有,则找CATALINA_HOME.然后找这个变量所指的目录下的conf文件夹,从中读取配置文件.最重要的配置文件:server.xm ...
- spring cloud 配置纲要Properties
名称 默认 描述 encrypt.fail-on-error true 标记说,如果存在加密或解密错误,进程将失败. encrypt.key 对称密钥.作为一个更强大的替代方案,考虑使用密钥库. ...
- 2、Spring Boot配置
1.配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoo ...
- Spring Boot -- 配置切换指南
一般在一个项目中,总是会有好多个环境.比如: 开发环境 -> 测试环境 -> 预发布环境 -> 生产环境 每个环境上的配置文件总是不一样的,甚至开发环境中每个开发者的环境可能也会有一 ...
- spring 定时任务配置
1.(易)如何在spring中配置定时任务? spring的定时任务配置分为三个步骤: 1.定义任务 2.任务执行策略配置 3.启动任务 (程序中一般我们都是到过写的,直观些) 1.定义任务 < ...
随机推荐
- 检测是否安装了 .NET Framework 3.5
此脚本是为 Internet Explorer 设计的. 其他浏览器可能在 UserAgent 字符串中不包含 .NET CLR 信息. <HTML> <HEAD> &l ...
- ubuntu 13.04下sublime text 3使用中文输入法
主要思路参考 http://blog.yanwen.org/archives/1955.html libsublime-imfix.so 这个库自己编译和从他这下载的 md5一样.可以不用编译了.直接 ...
- whu 1464 deal with numbers
WHU 1464 deal with numbers 题意: 给你一串数字,对着串数字有三项操作: Minus a,b,c:对区间[a,b]总的每个数都减c. Division a,b,c:对区间[ ...
- MongoDB介绍及下载与安装
MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的.他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型.M ...
- Reactive native 项目创建失败如何处理
首先感谢党的英明决策. 一开始我总觉得Awesomeproject这个名字是固定的,和我有同感的同学请举手. 其实我们可以起任意的名字,执行native react init碰到的最大的问题是 npm ...
- Android自定义下拉刷新
网上的下拉刷新功能很多,不过基本上都是隐藏header的,而项目里面需要只隐藏部分的header,类似QQ好友动态的效果,修改了一些现有的,最后有很多问题,所以就自己自定义了一个,逻辑也很简单,首先就 ...
- iphone 3G\3GS 超详细拆机教程
更为直观的iphone视频拆机教程: http://bbs.app111.com/thread-243147-1-1.html 第一步: 准备好所需工具 iphone一台....吸盘一个..屏幕布一块 ...
- c# 泛型List的定义、作用、用法
定义:List<T>类表示可通过索引访问的对象的强类型列表,提供用于对列表进行搜索.排序和操作的方法. 作用: 泛型最常见的用途是泛型集合 我们在创建列表类时,列表项的数据类型可能是int ...
- ECSHOP在线手册布局参考图--文章详情页 article.dwt
A.购物车 1,设置方法 程序自动读取购物车的商品数量 2,代码相关 cart.lbi 中 {insert_scripts files='transport.js'} <div clas ...
- NSTimer、 NSTask、 NSThread 和 NSRunloop 之间的区别
NSTimer是一个计时器对象,方法调用在对未来的选择对象. NSThread是一个线程类. 也就是创建一个线程. NSTask类是一个过程,一种方式运行程序从您的其他程序. NSOperation是 ...