通过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.定义任务 < ...
随机推荐
- MapReduce概述,原理,执行过程
MapReduce概述 MapReduce是一种分布式计算模型,运行时不会在一台机器上运行.hadoop是分布式的,它是运行在很多的TaskTracker之上的. 在我们的TaskTracker上面跑 ...
- HUOJ-10857 最大的面积 凸包+DP
题目链接:http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=10857&courseid=55 比赛的时候 ...
- 曝光卖假币的店铺和旺旺ID
1:店铺名称:九玖邮币 掌柜ID:九玖邮币[此人较贼,价格只比我们低一点,图用的不太清晰的,或者直接用真品图,而且卖假币卖到2钻了,很多人上当了.]1.5 店铺名称:聚鑫钱币 掌柜ID:聚鑫钱币 [1 ...
- 13个不容错过的Java项目
今天我们将整理一大波干货满满的Java示例代码与能力展示素材. GitHub可谓一座程序开发的大宝库,有些素材值得fork,有些则能帮助我们改进自有代码或者学习编程技能.无论如何,开发工作当中我们几乎 ...
- [iOS基础控件 - 4.3] APP列表 xib的使用
A.storyboard和xib 1.storyboard: 相对xib较重量级,控制整个应用的所有界面 2.xib: 轻量级,一般用来描述局部界面 B.使用 1.新建xib文件 New File ...
- [一]JQueryMobile简介
JQueryMobile 基于JQuery,实现对不同尺寸手机屏幕的支持,提供了许多组件,以及对于手机端的常用事件(touch.tap.taphold) 如何使用 1.引入jquery.js.jque ...
- IPO
Initial Public Offerings,简称IPO,首次公开募股(Initial Public Offerings,简称IPO):是指一家企业或公司 [1] (股份有限公司)第一次将它的股份 ...
- iOS动画详解(二)
UIImage常用的绘图操作 一个UIImage对象提供了向当前上下文绘制自身的方法.我们现在已经知道如何获取一个图片类型的上下文并将它转变成当前上下文. 平移操作:下面的代码展示了如何将UI ...
- MinGW安装和使用总结
0.前言 最近对开源编译平台和编译器产生了兴趣,借博客平台总结一些东西(包括minGW,eclipse,sourcery和GDB调试等内容).总感觉时间一长某些东西自己都会忘记,过段时间回头看看自己的 ...
- Android develop tricks——整理自国外的一些Blog
ViewDragHelper --视图拖动是一个比較复杂的问题.这个类能够帮助解决不少问题.假设你须要一个样例,DrawerLayout就是利用它实现扫滑.Flavient Laurent 还写了一些 ...