目的
有些特定的場景,我們需要讓QLExpress幫我們調用某個bean(比如dao執行sql或者某個service執行業務代碼),這個時候我們需要拿到dao或者service,因爲QLExpress本身是不依賴spring的,所以需要對QLExpress做擴展,讓它可以管理bean,這樣就可以滿足更多的需求啦
場景
根據優惠券ID查詢優惠券詳細信息
couponCardOpenService.queryCouponCardByCardId(QueryCouponCardByCardIdRequest)
couponCardOpenService是外部的dubbo服務,我們把這個方法調用封裝成自己的一個bean方法調用,封裝後的代碼如下:
public interface YhManager {
BaseResponse<CouponCardDto> getCouponCardById(Long cardId);
}
@Service(value="YhManager ")
public class YhManager Impl implements YhManager {
private static final Logger logger = LoggerFactory.getLogger(MdsManagerImpl.class);
@Reference
private CouponCardOpenService couponCardOpenService;
@Override
public BaseResponse<CouponCardDto> getCouponCardById(Long cardId) {
QueryCouponCardByCardIdRequest QueryCouponCardByCardIdRequest = new QueryCouponCardByCardIdRequest();
QueryCouponCardByCardIdRequest.setCardId(cardId);
return couponCardOpenService.queryCouponCardByCardId(QueryCouponCardByCardIdRequest);
}
}
封裝成本地bean的調用方法是爲了方便通過
applicationContext.getBean(MdsManager.class)獲取MdsManager這個bean
因爲如果直接獲取CouponCardOpenService這個外部bean的話會取不到;
擴展管理bean
使用IExpressContext進行擴展QLExpressContext,重寫get和put方法
public class QLExpressContext extends HashMap<String,Object> implements IExpressContext<String,Object> {
private ApplicationContext context;
public QLExpressContext(Map<String,Object> aProperties, ApplicationContext aContext){
super(aProperties);
this.context = aContext;
}
/**
* 根據key從容器裏面獲取對象
*
* @param key
* @return
*/
public Object get(Object key) {
Object object = super.get(key);
try {
if (object == null && this.context != null && this.context.containsBean((String)key)) {
object = this.context.getBean((String)key);
}
} catch (Exception e) {
throw new RuntimeException("表達式容器獲取對象失敗", e);
} return object;
}
/**
* 把key-value放到容器裏面去
*
* @param key
* @param value
*/ public Object put(String key, Object value) { return super.put(key, value); }
}
利用ApplicationContextAware 來獲取ApplicationContext上下文
@Service
public class QlExpressRunner implements ApplicationContextAware {
private Logger logger = LoggerFactory.getLogger(QlExpressRunner.class);
private ApplicationContext applicationContext;
private ExpressRunner runner;
@Override
public void setApplicationContext(ApplicationContext context) {
this.applicationContext = context;
if(runner == null){
runner = new ExpressRunner();
logger.info("runner = new ExpressRunner()");
}
}
public Object execute(String text,Map<String,Object> context) {
IExpressContext<String,Object> expressContext = new QLExpressContext(context,this.applicationContext);
try{
//此處可以初始化宏函數.....
//addFunctionOfServiceMethod
runner.addFunctionOfServiceMethod("根據cardId查詢優惠券card信息",applicationContext.getBean(MdsManager.class),"getCouponCardById",new Class[]{Long.class},null);
return runner.execute(text, expressContext, null, true, false);
}catch(Exception e){
logger.error("qlExpress運行出錯!",e);
} return null;
}
}
IExpressContext<String,Object> expressContext = new QLExpressContext(context,this.applicationContext);
runner.addFunctionOfServiceMethod("根據cardId查詢優惠券card信息",applicationContext.getBean(MdsManager.class),"getCouponCardById",new Class[]{Long.class},null);
這樣就可以完美地取到applicationContext了;
調用代碼:
String statement = "根據cardId查詢優惠券card信息(c)";
Long cardId = 3164l;
Map<String, Object> innerContext = new HashMap<String, Object>();
innerContext.put("c",cardId);
Object result;
result = runner.execute(statement, innerContext);
System.out.println(JSON.toJSON(result));
表達式”根據cardId查詢優惠券card信息(c)“其實就是告訴了QLExpress執行
yHManager.getCouponCardById(id);