`
express_wind
  • 浏览: 28337 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

QLExpress脚本语言技术讲解(4)------扩展QLExpress来管理spring的bean,写出简单的脚本语言框架

 
阅读更多

类似淘宝、腾讯之类的复杂业务系统一般都采用分布式的系统集群结构,每一个独立的子系统负责一块业务,这样做主要是为了使业务更加分离,专人负责专 人的应用系统,同时降低系统的耦合性,增强系统的安全和稳定性。同时分布式的数据库和应用结构,使很多复杂的业务规则也变成了一个特定的系统调用。

比如“支付订单(12781)”,需要调用一个交易中心的支付订单API。

 

本章主要介绍的是如何通过扩展QlExpress的上下文,来管理和调用spring的bean。以及在出现系统故障的时候,编写批量脚本来快速的恢复子系统的间系统调用。

 

我们来看这个场景:

 

例如因为处理订单流程的平台因为网络原因暂停了很多用户的流程,导致有一大堆的订单号等待处理(12781,12788,12312)。


 对应的qlExpress的参数设置原理图:

 

这个控制台的界面大概是这样设计的:

 

****************************************************

用户上下文:idList ={12781,12788,12312}

***************************************************

执行的脚本:orderService.orderPay(id);

***************************************************


 

问题是 QlExpress虽然可以解读orderService.orderPay(id)是个bean的方法调用,但是orderService这个bean怎么从spring获取到和脚本关联起来呢?

答案是扩展QlExpress原来的上下文。

 

 上下文的扩展类,实现了 IExpressContext:

 

import java.util.HashMap;
import java.util.Map;
import org.springframework.context.ApplicationContext;

import com.ql.util.express.IExpressContext;

@SuppressWarnings("serial")
public class QLExpressContext extends HashMap<String,Object> implements IExpressContext<String,Object>{
 
 private ApplicationContext context;

    public QLExpressContext(ApplicationContext aContext){
     this.context = aContext;
    }
    public QLExpressContext( Map<String,Object> aProperties,ApplicationContext aContext){
     super(aProperties);
     this.context = aContext;
    }
   
 /**
  * 抽象方法:根据名称从属性列表中提取属性值
  */
 public Object get(Object name) {
  Object result = null;
  result = super.get(name);
  try{
   if (result == null &&this.context!= null && this.context.containsBean((String)name)) {
    //如果在Spring容器中包含bean,则返回String的Bean
    result = this.context.getBean((String)name);
   }
  }catch(Exception  e){
   throw new RuntimeException(e); 
  }
  return result;
 }

 public Object  put(String name, Object object) {
    if(name.equalsIgnoreCase("myDbData")){
     throw new RuntimeException("没有实现");
    }
       return  super.put(name,object);
 }


}

执行的工具类,实现了ApplicationContextAware 接口

import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressContext;
import com.taobao.upp.sc.common.expression.QLExpressContext;

public class QlExpressUtil implements ApplicationContextAware{
 
 private static ExpressRunner runner ;
    static{  
     runner = new ExpressRunner();
    }
    private static boolean isInitialRunner = false;
 private ApplicationContext applicationContext;//spring上下文

 
 /**
  *
  * @param statement 执行语句
  * @param context 上下文
  * @throws Exception
  */
 @SuppressWarnings("unchecked")
 public Object execute(String statement,Map<String,Object> context) throws Exception
 {
  initRunner(runner);
  IExpressContext expressContext = new QLExpressContext(context,applicationContext);
  statement = initStatement(statement);
  return runner.execute(statement, expressContext, null, true, false); 
 }
 
 /**
  * 在此处把一些中文符号替换成英文符号
  * @param statement
  * @return
  */
 private String initStatement(String statement) {
  return statement.replace("(", "(").replace(")", ")").replace(";", ";").replace(",", ",").replace("“", "\"").replace("”", "\"");  
 } 
 private  void initRunner(ExpressRunner runner)
 {
  if(isInitialRunner == true){
   return ;
  }
  synchronized (runner) {
   if(isInitialRunner == true){
    return ;
   }
   try {
    //在此可以加入预定义函数
   } catch (Exception e) {
    throw new RuntimeException("初始化失败表达式",e);
   }   
  }
  isInitialRunner = true;  
 } 
 public void setApplicationContext(ApplicationContext aContext)
 throws BeansException {
  applicationContext = aContext;
 }
 
}

 

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.map.ListOrderedMap;

控制台代码的实现

 public class ClientQlExpressTest {


	/**
	 * 
	 * @param idList
	 * @param text
	 * @param resultMap
	 */
	public void run(List<Long> idList, String text, ListOrderedMap resultMap) {

		for (Long id : idList) {

			Map<String, Object> innerContext = new HashMap<String, Object>();

			innerContext.put("id", id);

			Object result = qlExpressUtil.execute(statement, innerContext);

			resultMap.put(id, result);

		}

	}

}

 

最终我们可以在resultMap看到类似这样的结果:

 

12781 true
12788 false
12312 true

 

 

就简单的几个类实现一个很强大的java脚本语言执行工具,是不是很犀利呢!

 

orderService.orderPay(id); 

这个脚本虽然对于java开发工程师师没有问题的,但是对于技术支持人员,显然还是太难记住了,下篇我们将进行宏定义,变成

支付订单(id)



 PS:

因为本身QlExpressRunner本身不依赖spring,所以这个例子就不在QlExpress的源代码demo中,如果有疑问可以联系我,

旺旺:天樵

QQ:371754252

 



  


  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics