我是靠谱客的博主 想人陪眼睛,最近开发中收集的这篇文章主要介绍基于Groovy的规则脚本引擎,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

预研笔记
https://blog.csdn.net/weixin_34206899/article/details/87268761

protected RuleManager ruleMananger;
	public Map<String, Object> execute(String directoryName, String ruleName,
			Map<String, Object> problem, String[] strings) {
		try {
			return ruleMananger.execute(directoryName, ruleName, problem, strings);
		} catch (EcadBaseException e) {
			e.printStackTrace();
			ruleMananger.storeRuleExceptionLog(null, e);
			throw new BusinessException(e.getMess());
		}
	}
public interface RuleManager extends BaseManager {
	
	
	public static final String ID = "序号";
	
	public static final String IDS = "序号集";
	
	public static final String DATE = "日期";
	
	public static final String START_DATE = "开始日期";
	
	public static final String END_DATE = "结束日期";
	
	public static final String BALANCE = "结算标识";
	
	Map<String, Object> execute(String directoryName,String ruleName,
			Map<String, Object> problem,String[] strings);
	
	Map<String, Object> execute(String directoryName,String ruleName,
			Map<String, Object> problem);
	
	
	List<Map<String,Object>> getAllRuleTableDetail(String[] binds,Object... objects);
	
	Object getSingleRuleTableDetail(String[] binds,Object... objects);
	
	Map<String,Object> getRuleTableDetail(String[] binds,Object... objects);
	
	List<Map<String,Object>> getMultipleRuleTableDetail(String[] binds,Object... objects);
	
	@Transactional
	void storeRuleExceptionLog(String gourpNo,String process,EcadBaseException ecadBaseException);
	
	@Transactional
	void storeRuleExceptionLog(String process,EcadBaseException ecadBaseException);
	
	@Transactional
	void refreshVersionHashCode();
	
	
	Boolean isLoader();
}
package com.vtradex.rule.server.service.rule.pojo;

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

import org.springframework.util.Assert;

import com.vtradex.engine.exception.EcadBaseException;
import com.vtradex.engine.groovy.Launcher;
import com.vtradex.rule.server.loader.IRuleTableLoader;
import com.vtradex.rule.server.loader.IThornRuleLoader;
import com.vtradex.rule.server.model.exception.RuleExceptionLog;
import com.vtradex.rule.server.model.rule.Directory;
import com.vtradex.rule.server.model.rule.Version;
import com.vtradex.rule.server.service.rule.RuleManager;
import com.vtradex.thorn.server.exception.BusinessException;
import com.vtradex.thorn.server.model.security.User;
import com.vtradex.thorn.server.service.pojo.DefaultBaseManager;
import com.vtradex.thorn.server.util.BeanUtils;
import com.vtradex.thorn.server.util.Constant;
import com.vtradex.thorn.server.web.security.UserHolder;


public class DefaultRuleManager extends DefaultBaseManager implements
		RuleManager {
	
	private IThornRuleLoader thornRuleLoader;
	private IRuleTableLoader ruleTableLoader;
	
	public IThornRuleLoader getIThornRuleLoader(){
		if(thornRuleLoader == null){
			thornRuleLoader = (IThornRuleLoader)applicationContext.getBean("thornRuleLoader");
		}
		return thornRuleLoader;
	}
	
	public IRuleTableLoader getIRuleTableLoader(){
		if(ruleTableLoader == null){
			ruleTableLoader = (IRuleTableLoader)applicationContext.getBean("ruleTableLoader");
		}
		return ruleTableLoader;
	}
	
	
	public Boolean isLoader(){
		return getIThornRuleLoader().isLoader() && getIRuleTableLoader().isLoader();
	}
	
	protected Directory getDirectoryByUnqie(String name){
		String hashCode = BeanUtils.getFormat(name);
		String hql = "FROM Directory directory WHERE directory.hashCode = :hashCode";
		return (Directory)commonDao.findByQueryUniqueResult(hql, new String[]{"hashCode"}, new Object[]{hashCode});
	}
	
	public Map<String, Object> execute(String directoryName,String ruleName,
			Map<String, Object> problem){
		return execute(directoryName, ruleName, problem,new String[]{
				Constant.NULL,Constant.NULL,Constant.NULL,
				Constant.NULL,Constant.NULL});
	}
	
	public Map<String, Object> execute(String directoryName,String ruleName,
			Map<String, Object> problem,String[] strings){
		if(strings == null || strings.length != 5){
			throw new BusinessException("bind.ref.config.error");
		}
		Directory directory = getDirectoryByUnqie(directoryName);
		if(directory == null){
			throw new BusinessException("directoryName.not.find");
		}
		if(!directory.isUpline()){
			throw new BusinessException("directoryName.is.not.upLine");
		}
		List<String> keys = new ArrayList<String>(problem.keySet());
		Launcher launcher = getIThornRuleLoader().getLauncher(BeanUtils.getFormat(directoryName,ruleName),directoryName);
		try {
			Assert.notNull(launcher);
		} catch (IllegalArgumentException e) {
			throw new BusinessException("not.find.rule");
		}
		Map result = new HashMap();
		try {
			result = launcher.calculate(problem,strings);
		}catch (EcadBaseException e) {
			e.printStackTrace();
			e.setValue(directoryName, ruleName);
			throw e;
		}catch (Exception e) {
			e.printStackTrace();
			EcadBaseException ebe = new EcadBaseException("规则语法使用出错,请检查规则各取值或函数调用问题!",e);
			ebe.setValue(directoryName, ruleName);
			throw ebe;
		}
		for(String str : keys){
			result.remove(str);
		}
		keys = new ArrayList<String>(result.keySet());
		for(String str : keys){
			if(result.get(str) == null){
				result.remove(str);
			}
		}
		return result;
	}

	public void storeRuleExceptionLog(String groupNo,String process,EcadBaseException ecadBaseException){
		RuleExceptionLog log = new RuleExceptionLog(groupNo,process,ecadBaseException);
		User user = UserHolder.getUser();
		if(user == null){
			String hql = "FROM User user WHERE user.loginName = 'admin'";
			user = (User)commonDao.findByQueryUniqueResult(hql, new String[]{}, new Object[]{});
		}
		log.setUserInfo(user.getId(), user.getName());
		commonDao.store(log);
	}
	
	public void storeRuleExceptionLog(String process,EcadBaseException ecadBaseException){
		storeRuleExceptionLog(null,process,ecadBaseException);
	}
	
	
	public void refreshVersionHashCode(){
		List<Version> versions = loadAll(Version.class);
		for(Version v : versions){
			v.gerneratHashCode();
		}
	}

	@Override
	public List<Map<String, Object>> getAllRuleTableDetail(
			String[] binds, Object... objects) {
		Date invalidDate = new Date();
		return (List<Map<String,Object>>)ruleTableLoader.getAllRuleTableDetail(invalidDate, binds, objects);
	}

	@Override
	public Object getSingleRuleTableDetail(String[] binds,
			Object... objects) {
		Date invalidDate = new Date();
		return ruleTableLoader.getSingleRuleTableDetail(invalidDate, binds, objects);
	}

	@Override
	public Map<String, Object> getRuleTableDetail(String[] binds,
			Object... objects) {
		Date invalidDate = new Date();
		return (Map<String,Object>)ruleTableLoader.getRuleTableDetail(invalidDate, binds, objects);
	}

	@Override
	public List<Map<String, Object>> getMultipleRuleTableDetail(
			String[] binds, Object... objects) {
		Date invalidDate = new Date();
		return (List<Map<String,Object>>)ruleTableLoader.getMultipleRuleTableDetail(invalidDate, binds, objects);
	}
}

Directory getDirectoryByUnqie(String name) 数据库查询规则

package com.vtradex.rule.server.model.rule;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;

import com.vtradex.rule.client.page.model.CustomDirectory;
import com.vtradex.thorn.server.model.Entity;
import com.vtradex.thorn.server.util.BeanUtils;


public class Directory extends Entity {

	private static final long serialVersionUID = 1L;
	
	private String name;//目录名称
	private boolean root = false;//是否规则根目录
	private boolean upline = false;//是否上线
	private Date updatedTime = new Date();//更新时间(仅对规则根目录有效,其他目录没有意义)
	private Directory parent;
	private Set<Directory> children = new HashSet<Directory>();//子目录
	private Set<Rule> rules = new HashSet<Rule>();
	private Set<DataSource> dataSources = new HashSet<DataSource>();
	
	private String hashCode; 
	
	private String icon = "folder_table.gif";
	
	public boolean equals(Object obj) {
		if (!(obj instanceof Directory))
			return false;
		Directory castOther = (Directory) obj;
		return new EqualsBuilder().append(hashCode, castOther.hashCode).isEquals();
	}

	public int hashCode() {
		return new HashCodeBuilder().append(hashCode).toHashCode();
	}
	
	
	public void addChildren(Directory child){
		child.setParent(this);
		children.add(child);
	}
	
	public void addRule(Rule rule){
		rule.setDirectory(this);
		rules.add(rule);
	}
	
	public void addDataSource(DataSource dataSource){
		dataSource.setDirectory(this);
		dataSources.add(dataSource);
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public boolean isRoot() {
		return root;
	}
	public void setRoot(boolean root) {
		this.root = root;
	}
	public boolean isUpline() {
		return upline;
	}
	public void setUpline(boolean upline) {
		this.upline = upline;
	}
	public Date getUpdatedTime() {
		return updatedTime;
	}
	public void setUpdatedTime(Date updatedTime) {
		this.updatedTime = updatedTime;
	}
	public Directory getParent() {
		return parent;
	}
	public void setParent(Directory parent) {
		this.parent = parent;
	}
	public Set<Directory> getChildren() {
		return children;
	}
	public void setChildren(Set<Directory> children) {
		this.children = children;
	}
	public Set<DataSource> getDataSources() {
		return dataSources;
	}
	public void setDataSources(Set<DataSource> dataSources) {
		this.dataSources = dataSources;
	}
	
	public Set<Rule> getRules() {
		return rules;
	}

	public void setRules(Set<Rule> rules) {
		this.rules = rules;
	}

	public CustomDirectory getClientDirectory(){
		CustomDirectory customDirectory = new CustomDirectory();
		BeanUtils.copyEntity(customDirectory, this);
		if(parent != null){
			CustomDirectory customParent = new CustomDirectory();
			BeanUtils.copyEntity(customParent, parent);
			customDirectory.setCustomParent(customParent);
		}
		return customDirectory;
	}
	
	public String getHashCode() {
		return hashCode;
	}

	public void setHashCode(String hashCode) {
		this.hashCode = hashCode;
	}

	public String getIcon() {
		return icon;
	}

	public void setIcon(String icon) {
		this.icon = icon;
	}
	
	public void gerneratHashCode() {
		List<String> params = new ArrayList<String>();
		if(getRootDirectory() != null){
			params.add(getRootDirectory().getName());
		}
		params.add(name);
		this.setHashCode(BeanUtils.getFormat(params.toArray()));
	}
	
	public Directory getRootDirectory(){
		if(this.parent == null)return null;
		Directory directory = this.parent;
		while(directory.getParent() != null){
			directory = directory.getParent();
		}
		return directory;
	}
}

public Launcher getLauncher(String key,String ruleName) {
		if(ruleClazzs == null)return null;
		Class clazz = ruleClazzs.get(key);
		if(clazz == null){
			return null;
		}
		Launcher launcher = (Launcher) ClassUtil.newInstance(clazz, new Object[0]);
		launcher.setBeanFactory(applicationContext);
		launcher.setDirectoryName(ruleName);
		return launcher;
	}

规则上线加载进入spring容器

	public void afterPropertiesSet() throws Exception {
		thornRuleManager = (ThornRuleManager)applicationContext.getBean("thornRuleManager");
		new Thread(new Runnable() {
			public void run() {
				ruleClazzs = thornRuleManager.loadAllThornRule();
				isLoader = Boolean.TRUE;
			}
		}).start();
		
	}

数据库加载所有上线的规则

public Map<String, Class> loadAllThornRule() {
		String hql = "select directory.id FROM Directory directory where directory.upline = true";
		List<Long> ids = commonDao.findByQuery(hql);
		Map<String, Class> launchers = new HashMap<String, Class>();
		for (Long id : ids) {
			launchers.putAll(loadThornRuleByDirectory(id));
		}
		return launchers;
	}
public Map<String, Class> loadThornRuleByDirectory(Long id) {
		Map<String, Class> launchers = new HashMap<String, Class>();
		Directory directory = load(Directory.class, id);
		List<Rule> feeRule = getThornRuleByDirectory(id);
		StringBuffer subBuf = new StringBuffer();
		for (Rule sub : feeRule) {
			if (!sub.isMain()) {
				RuleReader rulesReader = (RuleReader) ClassUtil.newInstance(
						RuleParserReader.class,
						new Object[] { sub.decryptContent() });
				String parsedRule = rulesReader.read();
				subBuf.append("void " + sub.getName() + "(){rn" + parsedRule
						+ "}rn");
			}
		}

		for (Rule main : feeRule) {
			if (main.isMain()) {
				Class clazz = ecadLauncher.createLauncherClass(
						main.decryptContent(), subBuf.toString());
				
//				Launcher launcher = ecadLauncher.createLauncher(
//						main.decryptContent(), subBuf.toString());
//				launcher.setBeanFactory(beanFactory);
//				launcher.setDirectoryName(directory.getName());
				launchers.put(
						BeanUtils.getFormat(directory.getName(),
								main.getName()), clazz);
			}
		}
		return launchers;
	}

根据id和parentId加载directory -----》》》fore 加载所有对应的rules

Directory directory = load(Directory.class, id);
select * from bre_directory WHERE id=75
75	5cd816de2dd0e977bb62e07b152363fb	主规则	76	0	0	2015-08-13 14:23:04				0000-00-00 00:00:00		0000-00-00 00:00:00	0	

select * from bre_directory WHERE parent_id=75

List<Rule> feeRule = getThornRuleByDirectory(id);
select * from bre_rule WHERE directory_id=75
169	75	7ce3e8b5855fb0b401b8469eff223f83	1	分组号编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b9aa88ea3d6cf3a25330e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
170	75	d9f5bdf5fd19b0e7c64546581a12e876	1	调度单编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b99eca13ce811d595a30e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
171	75	a441873dd6c322f09b2d9c2ce0dd56c7	1	出库单编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b99eca13ce811d595a30e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
172	75	b2616ec129145ec3971c742199a33dbc	1	质量事故事件规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b986637b18d7bcaaa530e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
173	75	3b25707f35506449cb3fa9b776c95fe1	1	承运合同编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b90e339d5dae5d770c30e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
174	75	8754f10ee7337d5036b984550b6c42b4	1	订单编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b99eca13ce811d595a30e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
175	75	85c83ad5a132999c82ba20faf6a523df	1	开票通知单规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b99118a71e6978d2d130e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
176	75	c4ed7400ef9a3b90b1e75597f046504f	1	入库单编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b99eca13ce811d595a30e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
177	75	999d2b14866d9c3903d69e70ab07f40c	1	应收账单编码规则		433e96676abc012c1409234dbed0bcdb02758810eb9d36bf252fad9b6402a2b9aa88ea3d6cf3a25330e54e9a25f7dfe0				0000-00-00 00:00:00		0000-00-00 00:00:00	0	
Class clazz = ecadLauncher.createLauncherClass(main.decryptContent(), subBuf.toString());

	public Class createLauncherClass(String rule , String subRule) {
		rule = ParenOperateUtil.formatParen(rule);
		return launcherFactory.createGroovyClass(rule, subRule);
	}

  protected GroovyClassLoader loader = new GroovyClassLoader(parentLoader);

	public Class createGroovyClass(String rule, String subRule) {
		String str = launcherLoader.load(rule, subRule);
		if (log.isDebugEnabled()) {
			log.debug("【Rule's original】:" + str);
		}
		return loader.parseClass(str);
	}


/** Groovy模板文件的装载器 **/
	private ResourceReader templateReader;
	/** 配置的规则文件的装载器 **/
	private RuleReader rulesReader;
public String load(String rule , String subRule) {
		rulesReader = (RuleReader)ClassUtil.newInstance(
				RuleParserReader.class,new Object[]{rule});
    	Writer writer = new StringWriter();
    	try {
    		 new GStringTemplateEngine().createTemplate(templateReader.read()).make(getBind(subRule)).writeTo(writer);
		} catch (CompilationFailedException e) {
			throw new EcadException("compile.groovy.failuire", e);
		} catch (FileNotFoundException e) {
			throw new EcadException("template.grrovy.isnull", e);
		} catch (IOException e) {
			throw new EcadException("template.grrovy.isnull", e);
		} catch (ClassNotFoundException e) {
			throw new EcadException("template.grrovy.isnull", e);
		}
		return writer.toString();
	}


加粗样式

String.format()字符串常规类型格式化的两种重载方式
format(String format, Object… args) 新字符串使用本地语言环境,制定字符串格式和参数生成格式化的新字符串。
format(Locale locale, String format, Object… args) 使用指定的语言环境,制定字符串格式和参数生成格式化的字符串。

%s	字符串类型	“喜欢请收藏”
%c	字符类型	‘m’
%b	布尔类型	true
%d	整数类型(十进制)	88
%x	整数类型(十六进制)	FF
%o	整数类型(八进制)	77
%f	浮点类型	8.888
%a	十六进制浮点类型	FF.35AE
%e	指数类型	9.38e+5
%g	通用浮点类型(f和e类型中较短的)	不举例(基本用不到)
%h	散列码	不举例(基本用不到)
%%	百分比类型	%(%特殊字符%%才能显示%)
%n	换行符	不举例(基本用不到)
%tx	日期与时间类型(x代表不同的日期与时间转换符)	不举例(基本用不到)
  String str=null;
    str=String.format("Hi,%s", "小超");
    System.out.println(str);
    str=String.format("Hi,%s %s %s", "小超","是个","大帅哥");
    System.out.println(str);
    System.out.printf("字母c的大写是:%c %n", 'C');
    System.out.printf("布尔结果是:%b %n", "小超".equals("帅哥"));
    System.out.printf("100的一半是:%d %n", 100/2);
    System.out.printf("100的16进制数是:%x %n", 100);
    System.out.printf("100的8进制数是:%o %n", 100);
    System.out.printf("50元的书打8.5折扣是:%f 元%n", 50*0.85);
    System.out.printf("上面价格的16进制数是:%a %n", 50*0.85);
    System.out.printf("上面价格的指数表示:%e %n", 50*0.85);
    System.out.printf("上面价格的指数和浮点数结果的长度较短的是:%g %n", 50*0.85);
    System.out.printf("上面的折扣是%d%% %n", 85);
    System.out.printf("字母A的散列码是:%h %n", 'A');
Hi,小超
Hi,小超 是个 大帅哥
字母c的大写是:C 
布尔结果是:false 
100的一半是:50 
100的16进制数是:64 
100的8进制数是:144 
50元的书打8.5折扣是:42.500000 元
上面价格的16进制数是:0x1.54p5 
上面价格的指数表示:4.250000e+01 
上面价格的指数和浮点数结果的长度较短的是:42.5000 
上面的折扣是85% 
字母A的散列码是:41 
    public Map calculate(Map<String,Object> problem,String... binds) {
        this.binds = binds;
        this.setParams(problem);
        this.setResults("版本日期", new Date());
        this.currentLineNo = 0;
        this.variables.clear();
        this.funParams.clear();
            setResults( "流水号", 获取流水序列号( getValue('前缀'),6 )
 )

        return params;
    }
    private Object getValue(String key){
        return params.get(key);
    }
  public Object getBean(String name) {
        return beanFactory.getBean(name);
    }

规则保存

public Map storeRuleTableDetail(Map params){
		Map result = new HashMap();
		try {
			CustomVersion customVersion = (CustomVersion)params.get(RuleTableConstants.PARAM);
			params.remove(RuleTableConstants.PARAM);
			Version version = load(Version.class,customVersion.getId());
			Long id = (Long)params.get(RuleTableConstants.ID);
			RuleTableDetail detail = new RuleTableDetail();
			if(id != null){
				detail = load(RuleTableDetail.class,id);
			}
			params.remove(RuleTableConstants.ID);
			
			List<RuleTableItem> ruleTableItems = getRuleTableItem(version.getRuleTable().getId(),RuleTableItem.REFERENCE);
			for(Iterator it = params.keySet().iterator();it.hasNext();){
				String key = (String)it.next();
				String value = (String)params.get(key);
				if(StringUtils.isNotBlank(value)){
					value = value.trim();
				}
				RuleTableItem ruleTableItem = getRuleTableItem(ruleTableItems,key);
				if(ruleTableItem != null && ruleTableItem.getGradeItem()){
					value = StringUtils.replace(value, " ", "");
				}
				Ognl.setValue(key, detail, value);
			}
			if(!version.getRuleTable().isMultiple()){
				detail.setSequence("1");
			}
			detail.setVersion(version);
			detail.gerneratHashCode();
			commonDao.store(detail);
			getWorkflowManager().doWorkflow(version, "versionProcess.modify");
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			throw new BusinessException("保存规则表明细出错!");
		}
		return result;
	}
/** Generated Token Manager. */
  public RuleParserTokenManager token_source;
  SimpleCharStream jj_input_stream;

最后

以上就是想人陪眼睛为你收集整理的基于Groovy的规则脚本引擎的全部内容,希望文章能够帮你解决基于Groovy的规则脚本引擎所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(53)

评论列表共有 0 条评论

立即
投稿
返回
顶部