通过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.定义任务 < ...
随机推荐
- Chrome 浏览器跨域和安全访问问题 使用 chrome的命令行标记:disable-web-security 参数联调线上数据
做前端的,用Ajax获取数据,是常有的事情,同域下自然没问题了,如果是不同域获取数据,浏览器就有个同源策略的限制. 如图: Origin * is not allowed by Access-Cont ...
- 10行Java代码实现最近被使用(LRU)缓存
在最近的面试中,我曾被多次问到,怎么实现一个最近最少使用(LRU)的缓存.缓存可以通过哈希表来实现,然而为这个缓存增加大小限制会变成另一个有意思的问题.现在我们看一下怎么实现. 最近最少使用缓存的回收 ...
- HDU 1561 树形DP(入门)
题目链接: HDU 1561 The more, The Better #include <iostream> #include <cstdio> #include < ...
- 【数据结构】非常有用的hash表
这篇博客的目的是让尚未学会hash表的朋友们对hash表有一个直观的理解,并且能根据本文定义出属于自己的第一个hash表,但算不上研究文,没有深究概念和成功案例. 什么是has ...
- 知方可补不足~SQL数据库用户的克隆,SQL集群的用户同步问题
我们知道在为sqlserver建立功能数据库时,通过会为库再建立一个登陆名,而这个登陆名时,只用来管理这个数据库,这是安全的,正确的.
- iOS 转让APP
今天需要将一个客户的app转让到它公司的个人账号上,记录下来流程,给有需要的人方便查看. 上面这个是咨询了苹果的客户之后收到的邮件说明,有需要的大家自己仔细看看. 好了,进入正题: 一:转出方操作 1 ...
- EntityFramework 连接数据库出错
本文转载:http://www.cnblogs.com/shuang121/archive/2012/03/19/2406121.html 总结:选择“是”时,连接字符串的密码会暴露出来,“否”的时候 ...
- UIView中触摸事件touchBegin
UIView触摸事件touchBegin 等一系列方法 1)手指按下 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event; ...
- 【30】透彻了解inlining 的里里外外
1.inline方法相当于文本替换,不需要承担方法调用的额外开销,同时还有潜在的优势,文本替换后,编译器会进行代码优化.而对于方法调用,编译器没有能力进行代码优化. 2.显而易见,inline方法往往 ...
- android常见错误--INSTALL_FAILED_DEXOPT
出现上面的问题,是由于手机的内存不足导致的,需要清理一下手机的内存,然后就可以了