先介绍一下活动模块的背景
- 活动主要关系活动表和环节表,每个活动有特定的n个环节
- 活动主要分为两部分(我总结的):
- (1)、活动页面交互环节(intercation),由用户主动调用服务
- (2)、程序主动行为(automation),有用户活动期间投资或者新用户注册触发行为
1、新的活动引擎中,新增一个活动基类接口:
只有一个抽象方法,用于引擎自动执行的行为(例如投资以后送红包,以及新注册用户赠送礼物)
/**
* user zyu
* datetime 2017/3/22 13:34
* description
*/
public interface IBaseActivity {
void autoMation(Map<String,Object> parmMap);
}
2、活动具体实现类,实现IBaseActivity接口
/**
* user zyu
* datetime 2017/3/22 13:41
* description 活动模板
*/
@Service("simpleActivity")
public class SimpleActivity implements IBaseActivity {
/**
* method1
* @param parmMap
* @return
*/
public ReturnResult<Map<String,Object>> method1(Map<String,Object> parmMap){
/**
* 逻辑实现
* 返回数据
*/
return null;
}
/**
* method2
* @param parmMap
* @return
*/
public ReturnResult<Map<String,Object>> method2(Map<String,Object> parmMap){
/**
* 逻辑实现
* 返回数据
*/
return null;
}
@Override
public void autoMation(Map<String, Object> parmMap) {
/**
* 引擎自动行为逻辑实现
*/
}
}
3、提供通用的活动接口,用于引擎实例(通过Spring 反射实现),这里还要说一点,主要是踩的坑,开始使用的java原生的反射,但是spring 注入的机制就失效了,只能通过手动装配,这点网上大致是这么解释的:因为通过java原生的反射,没有创建类实例,所以类中的注入就不起作用
装载 baseActivity,这里的baseActivity是IBaseActivity类型
/**
* load baseActivity
* 装载 baseActivity
*/
if(activityMap.containsKey(activityCode)){
baseActivity = activityMap.get(activityCode);
}else {
ActivityInfo activityInfo = activityInfoService.getActivityInfoByCode(activityCode);
if(null !=activityInfo && null != activityInfo.getReflexClass()
&& !activityInfo.getReflexClass().equals("")){
baseActivity = SpringContextHolder.getBean(activityInfo.getReflexClass());
activityMap.put(activityCode , baseActivity);
}else {
resultData.setResultCode(0);
resultData.setErrorCode(ErrorConstants.PARAM_NOT_RIGHT);
printJson(resultData);
return null;
}
}
装载 method,方法名主要有调用服务方传递
/**
* load aClass and method
* 装载 aClass method
*/
if(metMap.containsKey((activityCode+methodName))){
method = metMap.get((activityCode+methodName));
}else {
if(classMap.containsKey(activityCode+"class")){
aClass = classMap.get(activityCode+"class");
}else {
aClass = baseActivity.getClass();
classMap.put((activityCode+"class") ,aClass);
}
method = ReflectionUtils.findMethod(aClass, methodName, Map.class);
metMap.put((activityCode+methodName) ,method);
}
resultData = (ReturnResult<Map<String, Object>>) ReflectionUtils.invokeMethod(method, baseActivity,parmMap);
出于性能考虑,增加了缓存机制
/**
* cache class and method
* 缓存反射类和方法
*/
public static Map<String,Class> classMap = new HashMap<String,Class>();
public static Map<String,IBaseActivity> activityMap = new HashMap<String,IBaseActivity>();
public static Map<String,Method> metMap = new HashMap<String,Method>();
4、修改表结构,在活动表中增加COLUMN1字段,用于存放SimpleActivity活动实现类的@Service注解;
而在环节表中增加COLUMN2字段,用于存放环节类型(主要有intercation和automation,具体解释参照上面)
5、在投资或者注册以后有一个映射类(此类的作用就是用作,活动期间投资送礼物和注册赠送礼品什么的),在此类的映射方法中使用反射,具体实现如下:
/**
* use new activity engine
* 使用新的活动引擎
*/
ActivityLink activityLink1 = activityLinkDao.findAutoMationLinkByActivityCode(activityCode);
if (null != activityLink1) {
try {
Map<String, Object> parmMap = new HashMap<String, Object>();
IBaseActivity baseActivity = null;
if (activityMap.containsKey(activityCode)) {
baseActivity = activityMap.get(activityCode);
} else {
if (null != ai && null != ai.getReflexClass()
&& !ai.getReflexClass().equals("")) {
baseActivity = SpringContextHolder.getBean(ai.getReflexClass());
activityMap.put(activityCode, baseActivity);
}
}
if (null != baseActivity) {
parmMap.put("parm1", null);
parmMap.put("parm2", null);
parmMap.put("parm3", null);
baseActivity.autoMation(parmMap);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/** new **/
使用这种模式主要有几点好处:
1、简化接口(活动模块提供一个通用接口)
2、增强可读性的可维护性
3、活动模块化,降低耦合度
4、插拔式