java 规则引擎_Java规则引擎

import com.googlecode.aviator.AviatorEvaluator;

import com.googlecode.aviator.Expression;

import com.googlecode.aviator.runtime.function.AbstractFunction;

import com.googlecode.aviator.runtime.function.FunctionUtils;

import com.googlecode.aviator.runtime.type.AviatorLong;

import com.googlecode.aviator.runtime.type.AviatorObject;

import com.googlecode.aviator.runtime.type.AviatorString;

import java.util.HashMap;

import java.util.Map;

/**

* 业务需求:

* "1小时,userid,在ip上,触发action 100次则产生报警"

*

* 表达式设计:

* "redisCount('1','hour',fields('userid,ip,action')) >= 100"

*

* 参考资料:https://blog.csdn.net/shihlei/article/details/84919881

*

* 事件报警抽象:

* 需求1:报警判断机制:多长时间内(由时间值和时间单位两个量描述)某个监控对象(允许有多个参数来描述)发生多少次某个事件,则触发一次报警。

*

* 需求2:报警沉默机制:多长时间内,最多触发一次报警。

*

*/

public class RuleEngineDemo {

public static void main(String[] args) {

//默认AviatorEvaluator以编译速度优先:

// AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE);

//你可以修改为运行速度优先,这会做更多的编译优化:

AviatorEvaluator.setOptimize(AviatorEvaluator.EVAL);

//注册自定义表达式函数

AviatorEvaluator.addFunction(new FieldsFunction());

AviatorEvaluator.addFunction(new RedisCountFunction());

//模拟用户指定规则

// String expression = "(redisCount('1','hour',fields('userid,ip,action')) >= 100)&&(redisCount('1','hour',fields('userid,ip,action')) <= 200)";

String expression = "redisCount('1','hour',fields('userid,ip,action')) <= 100";

Expression compiledExp = AviatorEvaluator.compile(expression);

//模拟运行时收到数据

Map fields = new HashMap<>();

fields.put("userid", "9527");

fields.put("ip", "127.0.0.1");

fields.put("phone", "18811223344");

fields.put("action", "click");

// 报警规则判断

Boolean needAlarm = (Boolean) compiledExp.execute(fields);

if (needAlarm) {

// send alarm message

System.out.printf("发生报警");

}

}

/**

* 获取字段,校验,生成redis key

*/

static class FieldsFunction extends AbstractFunction {

@Override

public AviatorObject call(Map env, AviatorObject fieldsStrObj) {

//获取可变参数

String fieldStr = fieldsStrObj.stringValue(env);

String[] fields = fieldStr.split(",");

StringBuilder redisKey = new StringBuilder();

System.out.println("FieldsFunction : " + fieldStr);

for (String f : fields) {

Object value = env.get(f);

if (value != null) {

redisKey.append(value.toString());

} else {

//TODO 参数合法性校验

}

redisKey.append(":");

}

//TODO key如果过长的话,会影响redis的性能

return new AviatorString(redisKey.toString());

}

public String getName() {

return "fields";

}

}

/**

* 使用key进行查询,获取redis中存的量且redis +1

*/

static class RedisCountFunction extends AbstractFunction {

@Override

public AviatorObject call(Map env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3) {

String period = FunctionUtils.getStringValue(arg1, env);

String timeUnit = FunctionUtils.getStringValue(arg2, env);//当前支持hour和minutes

String redisKey = FunctionUtils.getStringValue(arg3, env);

System.out.println("FieldsFunction : " + period + " , " + timeUnit + " , " + redisKey);

long expire = getExpireTime(period,timeUnit);

//TODO 读取redis

int redisCount = redisGetAndIncrease(redisKey, expire);

return new AviatorLong(redisCount);

}

/**

* 使用key进行查询,获取redis中存的量且redis +1

* 如果key不存在则

* @param redisKey

* @return

*/

private int redisGetAndIncrease(String redisKey, long expireTime) {

System.out.println("get count from redis : " + redisKey);

// TODO:检查redisKey是否存在,如果不存在则初始化并为其设置超时时间;如果存在则获取redis中存的量且redis +1

//这里模拟查询得到的值

return 300;

}

// 获取超时的秒时间

private long getExpireTime(String period,String timeUnit){

// 模拟一分钟后超时

return 60;

}

public String getName() {

return "redisCount";

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值