一、介绍

规则属性是您可以添加到业务规则以修改规则行为的附加规范。 在 DRL 文件中,您通常在规则条件和操作的上方定义规则属性,多个属性位于单独的行中,格式如下:

rule "rule_name"
// Attribute
// Attribute
when
// Conditions
then
// Actions
end

二、常见的规则属性

规则属性 解释 举例
salience 定义规则优先级,是一个整数。当在激活队列中排序时,salience的值越大,优先级越高 salience 99
enabled 定义规则是否启用. true 启用,false 禁用,默认值是true enabled true
date-effective 包含时间和日期的字符串,当当前时间大于date-effective时,该规则才会被激活。这个时间格式可以修改,见下方具体的用法 date-effective "4-5月-2022"
date-expires 设置规则的过期时间,时间格式和上方一样。 date-expires "4-5月-2022"
no-loop 布尔值,默认值为false, 定义当当前规则规则的结果修改了fact对象时,是否可以再次执行该规则。true:不可以, false:可以,可能会导致死循环。指的是当前规则的修改,如果别的规则修改了,还会导致该规则的触发 no-loop true
agenda-group Agenda groups允许您对agenda进行分区,以提供对规则组的更多执行控制。 只有获得焦点的议程组中的规则才能被激活。 ,但是这个里面有个特例,如果某个规则没有配置 agenda-group,但是它模式匹配成功了,那么会被分到默认的组(main),这个main组的规则也会执行。 agenda-group "GroupName"
auto-focus 布尔值,仅适用于Agenda-Group内的规则。当值为true时,下次激活该规则时,会将焦点自动给这个Agenda group auto-focus true
activation-group 表示该组下的规则只有一个规则会被执行,该组下其余激活的规则会被取消执行。 但是别的组激活的规则可能会被执行。 activation-group "GroupName"
duration long类型的值,如果在这个时间之后规则还成立,那么执行该规则 duration 1000
timer 一个字符串,标识用于调度规则的 int(间隔)或 cron 计时器定义。 Example: timer ( cron:* 0/15 * * * ? ) (every 15 minutes)
calendar 定义Quartz calendar用于调度规则。
lock-on-active 一个布尔值,仅适用于规则流组或议程组中的规则。 选择该选项后,下次规则的规则流组变为活动状态或规则的议程组获得焦点时,规则无法再次激活,直到规则流组不再处于活动状态或议程组失去焦点。 这是 no-loop 属性的更强版本,因为匹配规则的激活被丢弃,无论更新的来源如何(不仅是规则本身)。 此属性非常适合计算规则,其中您有许多修改事实的规则并且您不希望任何规则重新匹配和再次触发。 lock-on-active true
dialect 将 JAVA 或 MVEL 标识为用于规则中的代码表达式的语言的字符串。 默认情况下,该规则使用在包级别指定的方言。 此处指定的任何方言都会覆盖该规则的包方言设置。 dialect "JAVA"

三、部分规则属性案例

此处编写出规则文件和部分核心Java代码

1、salience

定义规则执行的优先级,salience的值越大,优先级越高

1、规则文件的编写

rule "salience_rule_1"
salience 4
when
then
System.out.println("rule 1");
end rule "salience_rule_2"
salience 3
when
then
System.out.println("rule 2");
end // 此处优先级的值是动态获取来的
rule "salience_rule_3"
salience $dynamicSalience
when
$dynamicSalience: Integer()
then
System.out.println("rule 3");
end

注意:

我们的salience_rule_3的优先级的值是动态来的,即是从工作内存中获取的。

2、java代码编写

public class DroolsSalienceApplication {
public static void main(String[] args) {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession"); // 向工作内存中插入一个Integer值,salience_rule_3 需要用到这个优先级
kieSession.insert(10); // 只匹配规则名称是已 salience_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("salience_")); kieSession.dispose();
}
}

kieSession.insert(10);此处向工作内存中插入一个值,将会匹配到salience_rule_3,然后动态修改它的优先级。

3、运行结果

rule 3
rule 1
rule 2

因为 salience 的值越大优先级越高,所以是这个顺序。

2、enabled

定义规则是否启用,true启用 false禁用

1、规则文件编写

package rules

rule "enabled_rule_1"
// 禁用此规则
enabled false
when
then
System.out.println("enabled_rule_1");
end rule "enabled_rule_2"
// 启用此规则,默认就是启用
enabled true
when
then
System.out.println("enabled_rule_2");
end

enabled_rule_2这个规则需要运行,enabled_rule_1这个规则不能运行。

2、java代码编写

/**
* 测试规则的启用和禁用
*/
public class DroolsEnabledApplication {
public static void main(String[] args) {
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
// 只匹配规则名称是已 enabled_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("enabled_"));
kieSession.dispose();
}
}

没有需要注意的地方

3、运行结果

enabled_rule_2

可以看到只有规则enabled_rule_2输出了结果,而enabled_rule_1被禁用了。

3、date-effective

定义规则什么时候启用,只有当前时间>规则时间才会启用。需要注意默认的时间格式,可以通过java代码进行修改。

1、规则文件编写

package rules
import java.text.SimpleDateFormat
import java.util.Date // 规则一:输出当前时间
rule "date_effective_rule_1"
when
then
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
end // 规则二: 该规则会在2022-05-18 10:54:26之后被激活
rule "date_effective_rule_2"
date-effective "2022-05-18 10:54:26"
when
then
System.out.println("date_effective_rule_2执行了,规则允许被执行的时间应该在2022-05-18 10:54:26之后");
end // 规则三: 该规则会在2023-05-18 10:54:26之后被激活
rule "date_effective_rule_3"
date-effective "2023-05-18 10:54:26"
when
then
System.out.println("date_effective_rule_3会在时间到了2023-05-18 10:54:26才激活");
end

规则一:输出当前时间

规则二: 该规则会在2022-05-18 10:54:26之后被激活

规则三: 该规则会在2023-05-18 10:54:26之后被激活

2、java代码编写

/**
* 测试规则在执行的时间之后才能执行
*/
public class DroolsDateEffectiveApplication {
public static void main(String[] args) {
// 设置日期格式,否则可能会报错(Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]])
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
// 只匹配规则名称是已 date_effective_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("date_effective_"));
kieSession.dispose();
}
}

需要注意System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");这句,这个修改drools中的日期格式,因为规则中写的日期格式为date-effective "2023-05-18 10:54:26"而默认的格式为d-MMM-yyyy,不修会报错。

3、运行结果

当前时间:2022-05-18 10:59:38
date_effective_rule_2执行了,规则允许被执行的时间应该在2022-05-18 10:54:26之后

可以看到规则二执行了,规则三没有执行,因为规则三需要时间到达了2023-05-18 10:54:26才执行,而当前时间不符合。

4、注意事项

如果出现了Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]]这个错误该怎么解决了,这是因为日期格式不正确。需要在java代码中进行如下设置System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss")

4、date-expires

定义规则的过期时间,即规则到了该时间之后就不可使用了。和date-effective的用法类似,此处就不演示了。

5、no-loop

定义当当前规则的结果修改了fact对象时,是否可以再次执行该规则。可以防止死循环

1、规则文件编写

package rules
import java.util.concurrent.TimeUnit
import java.text.SimpleDateFormat
import java.util.Date rule "no_loop_rule_1"
no-loop true
when
$i: Integer(intValue() < 20)
then
modify($i){
}
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " no_loop_rule_1 i=" + $i);
end rule "no_loop_rule_2"
no-loop false when
$i: Integer(intValue() < 20)
then
modify($i){
}
TimeUnit.SECONDS.sleep(1);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " no_loop_rule_2 i=" + $i);
end

解释:

no_loop_rule_1no-loop true表示如果当前规则的RHS部分,对Fact对象进行了修改,则不会再次触发该规则。那如果是no_loop_rule_2修改了,会导致该规则的触发吗?答案是会触发,如果我不想被触发呢?那么使用lock-on-active可以实现。

no_loop_rule_2no-loop false表示如果当前规则的RHS部分,对Fact对象进行了修改,那么还会再次匹配这个规则。

2、java代码编写

/**
* 测试规则是否可以再次被执行
*/
public class DroolsNoLoopApplication {
public static void main(String[] args) throws InterruptedException {
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
kieSession.insert(10);
// 只匹配规则名称是已 no_loop_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("no_loop_"));
// 睡眠5s,使规则文件中的规则执行完
TimeUnit.SECONDS.sleep(5);
kieSession.dispose();
}
}

此处 java 代码,睡眠了5s,是为了让规则执行。

3、运行结果

2022-05-18 11:42:29 no_loop_rule_1 i=10
2022-05-18 11:42:31 no_loop_rule_2 i=10
2022-05-18 11:42:31 no_loop_rule_1 i=10
2022-05-18 11:42:32 no_loop_rule_2 i=10

解释:

2022-05-18 11:42:29 no_loop_rule_1 i=10: no_loop_rule_1被触发,由于RHS部分使用了modify修改了规则内存中的对象,但是该规则存在 no-loop true 的属性,所以该规则没有再次被触发,即只输出了一次。

2022-05-18 11:42:30 no_loop_rule_2 i=10 2022-05-18 11:42:30 no_loop_rule_1 i=10 此时规则 no_loop_rule_2 执行了,由于该规则的 no-loop 为 false 并且使用了 modify 方法,所以该规则多次被触发了,从结果上看,貌似规则 no_loop_rule_1 又再次被触发了,不是应该不被触发吗,因为设置了no-loop true?因为这是no_loop_rule_2导致no_loop_rule_1触发的,而no_loop只对自身的RHS修改有效。

疑问:

那如果将 no-loop换成lock-on-active结果会一样吗?可以自己尝试一下看看结果。

6、agenda-group

将被模式匹配成功后的规则,进行分组,只有获得焦点的组,才可以执行规则。但是这个里面有个特列,如果某个规则在模式匹配,匹配成功了,但是没有配置agenda-group,那么它会被分配到main组,这个main组的规则总是执行的。

agenda-group的数据结构就类似stack,激活的组是在栈顶。参考如下图:

参考链接: https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools

1、规则文件编写

package rules

/**
agenda-group 的数据结构类似与栈,激活的组会被放置在栈顶,
`main`是默认组,总是存在的,即没有配置agenda-group的就是`main`,
`main`总是会执行的。
*/ rule "agenda_group_001_rule_1"
agenda-group "group-001"
when
then
System.out.println("agenda_group_001_rule_1");
end rule "agenda_group_001_rule_2"
agenda-group "group-001"
when
then
System.out.println("agenda_group_001_rule_2");
end rule "agenda_group_002_rule_3"
agenda-group "group-002"
when
then
System.out.println("agenda_group_002_rule_3");
end rule "agenda_group_no_group_rule_4"
when
then
System.out.println("agenda_group_no_group_rule_4");
end

注意: 此处其实是 存在 3个组的,agenda_group_no_group_rule_4如果模式匹配成功后会被分配到main组,main总是会被执行的。

2、java代码编写

/**
* 测试规则分组
*/
public class DroolsAgendaGroupApplication {
public static void main(String[] args) {
// 设置日期格式,否则可能会报错(Wrong date-effective value: Invalid date input format: [2022-05-18 10:54:26] it should follow: [d-MMM-yyyy]]])
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession"); // 激活组
kieSession.getAgenda().getAgendaGroup("group-001").setFocus(); // 只匹配规则名称是已 agenda_group_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("agenda_group_"));
kieSession.dispose();
}
}

激活group-001分组。

3、运行结果

agenda_group_001_rule_1
agenda_group_001_rule_2
agenda_group_no_group_rule_4

解释:

agenda_group_no_group_rule_4为什么会被输出呢?它没有定义agenda-group啊,而且我们激活的也是group-001分组,它不应该输出啊。这是应为这个规则模式匹配成功后被分配到了默认的main组,而main组一定会被执行的。

7、auto-focus

设置某个agenda-group默认获取到焦点,和在java代码中使用kieSession.getAgenda().getAgendaGroup("group-001").setFocus();或在drl文件中使用drools.setFocus(..)一样。

8、activation-group

处于该分组中激活的规则,同一个组下,只有一个规则可以执行,其余的会被取消执行。但是别的组中激活的规则还是可以执行的。

1、规则文件编写

package rules

rule "activation_group_001_rule_1"
activation-group "group-001"
salience 1
when
then
System.out.println("activation_group_001_rule_1");
end rule "activation_group_001_rule_2"
activation-group "group-001"
salience 2
when
then
System.out.println("activation_group_001_rule_2");
end rule "activation_group_002_rule_3"
activation-group "group-002"
when
then
System.out.println("activation_group_002_rule_3");
end rule "activation_group_no_group_rule_4"
when
then
System.out.println("activation_group_no_group_rule_4");
end

activation-group "group-001"此处对这个组的规则指定了优先级,优先级高的先执行,执行完之后,该组别的规则不执行。

2、java代码编写

public class DroolsActivationGroupApplication {
public static void main(String[] args) {
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
// 只匹配规则名称是已 activation_group_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("activation_group_"));
kieSession.dispose();
}
}

3、运行结果

activation_group_001_rule_2
activation_group_002_rule_3
activation_group_no_group_rule_4

可以看到分组group-001中有2个规则,但是只执行了一个规则。

9、duration

long类型的值,单位毫秒,如果在这个时间之后规则还成立,那么执行该规则。

1、规则文件编写

package rules
import java.text.SimpleDateFormat
import java.util.Date rule "duration_rule_1"
// 延迟1s后执行规则
duration 1000
when
$i: Integer(intValue() < 10)
then
System.out.println(Thread.currentThread().getName() + ": " +
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())+
" duration_rule_1 $i:"+$i);
end

定义规则延迟1s后进行执行。

2、java代码编写

/**
* 在多少毫秒后,如果条件还成立,则触发该规则
*/
public class DroolsDurationApplication {
public static void main(String[] args) throws InterruptedException {
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession"); FactHandle factHandle = kieSession.insert(3);
// 只匹配规则名称是已 duration_ 开头的规则,忽略其余的规则
new Thread(() -> {
// 调用此方法会阻塞调用线程,直到 `kieSession.halt();`的调用
System.out.println("当前时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
kieSession.fireUntilHalt(new RuleNameStartsWithAgendaFilter("duration_"));
}, "fire-thread").start(); // 如果修改这个值,使得规则的条件不成立,看规则是否还执行
kieSession.update(factHandle, 4); TimeUnit.SECONDS.sleep(2);
kieSession.halt(); kieSession.dispose();
}
}

注意:

1、我们调用出发所有规则执行的方法不在是fireAllRules而是fireUntilHalt

2、fireUntilHalt的调用会阻塞线程,直到调用halt方法,因此fireUntilHalt需要放置到另外的线程中调用。而且我们观察规则的执行,也是在这个线程中调用的。

3、运行结果

当前时间:2022-05-18 14:13:36
fire-thread: 2022-05-18 14:13:37 duration_rule_1 $i:4

可以看到,延迟1s后规则执行了。

4、疑问

如果我们在1s钟之内,将规则的条件修改成不成立,那么规则还执行吗?答案:不执行。

10、lock-on-active

rule flow groups or agenda groups配合使用。

需求:

我们有2个规则,并且同属于一个组,规则二执行完之后,工作内存中的Fact对象的值发生了变化,导致规则一满足执行的条件,而规则一已经执行一遍了,此处需要阻止规则二的触发导致规则一的出触发。使用lock-on-active 即可实现。

1、规则文件编写

package rules

import com.huan.drools.lockonactive.Person

rule "lock_on_active_rule_01"
agenda-group "group-001"
lock-on-active true
when
$p: Person(age < 18)
then
System.out.println("lock_on_active_rule_01: 用户:[" + $p.getName() + "]当前的年龄是:[" + $p.getAge() + "]");
end rule "lock_on_active_rule_02"
agenda-group "group-001"
when
$p: Person(name == "张三")
then
modify($p){
setAge(15)
}
System.out.println("lock_on_active_rule_02: 用户:[" + $p.getName() + "]当前的年龄是:[" + $p.getAge() + "]");
end

规则lock_on_active_rule_01加了lock-on-active true属性后,规则lock_on_active_rule_02修改Fact导致规则lock_on_active_rule_01的条件成立,此时规则也是不会执行的。

2、java代码编写

/**
* 一个简单的实体类
*
* @author huan.fu
* @date 2022/5/18 - 14:34
*/
@Getter
@Setter
@AllArgsConstructor
public class Person {
private String name;
private Integer age;
} public class DroolsLockOnActiveApplication {
public static void main(String[] args) {
System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
KieServices kieServices = KieServices.get();
KieContainer kieContainer = kieServices.getKieClasspathContainer();
KieSession kieSession = kieContainer.newKieSession("rule-attributes-ksession");
// 激活组
kieSession.getAgenda().getAgendaGroup("group-001").setFocus(); Person person = new Person("张三", 20);
kieSession.insert(person); // 只匹配规则名称是已 lock_on_active_ 开头的规则,忽略其余的规则
kieSession.fireAllRules(new RuleNameStartsWithAgendaFilter("lock_on_active_"));
kieSession.dispose();
}
}

3、运行结果

lock_on_active_rule_02: 用户:[张三]当前的年龄是:[15]

可以看到只有规则二执行了,说明阻止了规则一的执行。

四、完整代码

https://gitee.com/huan1993/spring-cloud-parent/tree/master/drools/drools-drl-rule-attributes

五、参考链接

1、https://docs.drools.org/7.69.0.Final/drools-docs/html_single/index.html#rules-attributes-ref_drl-rules

2、 https://stackoverflow.com/questions/6870192/understanding-agenda-group-in-drools

drools规则属性(rule attributes)的使用的更多相关文章

  1. Drools 规则文件语法概述

    概述(Overview) 以.drl为扩展名的文件,是Drools中的规则文件,规则文件的编写,遵循Drools规则语法.下面详细介绍一下Drools规则文件语法.具体参考官方文档: https:// ...

  2. Drools 规则引擎应用

    规则引擎-drools 1 .场景 1.1需求 商城系统消费赠送积分 100元以下, 不加分 100元-500元 加100分 500元-1000元 加500分 1000元 以上 加1000分 .... ...

  3. Drools 规则引擎应用 看这一篇就够了

    1 .场景 1.1需求 商城系统消费赠送积分 100元以下, 不加分 100元-500元 加100分 500元-1000元 加500分 1000元 以上 加1000分 ...... 1.2传统做法 1 ...

  4. Drools规则引擎入门指南(一)

    最近项目需要增加风控系统,在经过一番调研以后决定使用Drools规则引擎.因为项目是基于SpringCloud的架构,所以此次学习使用了SpringBoot2.0版本结合Drools7.14.0.Fi ...

  5. drools规则引擎初探

    https://www.cnblogs.com/yuebintse/p/5767996.html 1.drools是什么 Drools是为Java量身定制的基于Charles  Forgy的RETE算 ...

  6. Drools 规则引擎环境搭建

    一.关于 drools 规则引擎 前面写过一篇 Drools 规则引擎相关的文章,这篇文章主要记录一下规则引擎的环境搭建和简单示例.不熟悉 drools 的朋友可以看看这篇文章: 自己写个 Drool ...

  7. Drools规则引擎-如果判断某个对象中的集合是否包含指定的值

    规则引擎集合相关处理 在实际生产过程中,有很多关于集合的处理场景,比如一个Fact对象中包含有一个集合,而需要判断该集合是否包含某个值.而Drools规则引擎也提供了多种处理方式,比如通过from.c ...

  8. SpringBoot2 整合 Drools规则引擎,实现高效的业务规则

    本文源码:GitHub·点这里 || GitEE·点这里 一.Drools引擎简介 1.基础简介 Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的 ...

  9. drools规则语法(一)

    1.基本的匹配规则 1.1变量 drools使用匹配的方式对Fact进行比对, 比如 account : Account(balance > 100) 这个规则的含义就是在Fact中找到类型为A ...

随机推荐

  1. 如何解决Visual Studio 2017 运行后控制台窗口一闪就消失了

    出现这种情况的原因 安装使用Visual Studio 2017 后,用Ctrl+F5运行程序,结果控制台窗口一闪就没了,也没有出现"press any key to continue-&q ...

  2. vue-baidu-map 进入页面自动定位的解决方案!

    写在前面:我只是一个前端小白,文章中的提到可能会有不足之处,仅提供一个参考.若有不完善的地方,欢迎各位大佬指出!,希望对你有帮助! 好了,入正题.其实之前也被这问题困扰过,在网上也查了一番,没找到解决 ...

  3. java中异常(Exception)的定义,意义和用法。举例

    1.异常(Exception)的定义,意义和用法 我们先给出一个例子,看看异常有什么用? 例:1.1- public class Test {    public static void main(S ...

  4. JS 实现下拉框去重

    JS 实现下拉框去重 学习内容: 需求 总结: 学习内容: 需求 用 JS 下拉框去重 实现代码 <html> <head> <meta http-equiv=" ...

  5. smdms超市订单管理系统之登录功能

    一.超市订单管理系统准备阶段 Supermarket order management system 创建数据库 数据库代码放置如下 点击查看数据库address代码 CREATE TABLE `sm ...

  6. c++对c的拓展_编译检测的增强

    一:全局变量检测增强:c++编译对全局变量的声明定义有严格区别 //c中全局变量的声明及定义         //c++中全局变量的声明及定义        //c++全局变量写成下列形式则报错 in ...

  7. formdata收集数据

    通常在收集表单的时候我们都要涉及到绑定上传附件,这时候就可以用formdata的形式携带文件流上传给服务器. formData是ajax2.0(XMLHttpRequest Level2)新提出的接口 ...

  8. Color Constancy 颜色恒定性

    1:Color Constancy? 世界上并不存在颜色.颜色仅仅是我们的眼睛和大脑对不同可见光的波长进行的一层映射.也就说颜色只是我们大脑和视网膜处理的结果. 1.1 关键问题 我们的视觉系统有一个 ...

  9. Ubu18安装RabbitMQ

    RabbitMQ安装 https://www.jianshu.com/p/5c8c4495827f 安装 RabbitMQ基于erlang语言,需要先安装 sudo apt-get install e ...

  10. 在UnityUI中绘制线状统计图2.0

    ##在之前的基础上添加横纵坐标 上一期在这里:https://www.cnblogs.com/AlphaIcarus/p/16123434.html 先分别创建横纵坐标点的模板,将这两个Text放在G ...