Drools是一个基于java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效。

本文所使用的demo已上传 http://download.csdn.net/source/3002213

1、Drools语法

开始语法之前首先要了解一下drools的基本工作过程,通常而言我们使用一个接口来做事情,首先要穿进去参数,其次要获取到接口的实现执行完毕后的结果,而drools也是一样的,我们需要传递进去数据,用于规则的检查,调用外部接口,同时还可能需要获取到规则执行完毕后得到的结果。在drools中,这个传递数据进去的对象,术语叫 Fact对象。Fact对象是一个普通的java bean,规则中可以对当前的对象进行任何的读写操作,调用该对象提供的方法,当一个java bean插入到workingMemory中,规则使用的是原有对象的引用,规则通过对fact对象的读写,实现对应用数据的读写,对于其中的属性,需要提供getter setter访问器,规则中,可以动态的往当前workingMemory中插入删除新的fact对象。

规则文件可以使用 .drl文件,也可以是xml文件,这里我们使用drl文件。

规则语法:

package:对一个规则文件而言,package是必须定义的,必须放在规则文件第一行。特别的是,package的名字是随意的,不必必须对应物理路径,跟java的package的概念不同,这里只是逻辑上的一种区分。同样的package下定义的function和query等可以直接使用。

比如:package com.drools.demo.point

import:导入规则文件需要使用到的外部变量,这里的使用方法跟java相同,但是不同于java的是,这里的import导入的不仅仅可以是一个类,也可以是这个类中的某一个可访问的静态方法。

比如:

import com.drools.demo.point.PointDomain;

import com.drools.demo.point.PointDomain.getById;

rule:定义一个规则。rule "ruleName"。一个规则可以包含三个部分:

属性部分:定义当前规则执行的一些属性等,比如是否可被重复执行、过期时间、生效时间等。

条件部分,即LHS,定义当前规则的条件,如  when Message(); 判断当前workingMemory中是否存在Message对象。

结果部分,即RHS,这里可以写普通java代码,即当前规则条件满足后执行的操作,可以直接调用Fact对象的方法来操作应用。

规则事例:

rule "name"

no-loop true

when

$message:Message(status == 0)

then

System.out.println("fit");

$message.setStatus(1);

update($message);

end

上述的属性中:

no-loop : 定义当前的规则是否不允许多次循环执行,默认是false,也就是当前的规则只要满足条件,可以无限次执行。什么情况下会出现一条规则执行过一次又被多次重复执行呢?drools提供了一些api,可以对当前传入workingMemory中的Fact对象进行修改或者个数的增减,比如上述的update方法,就是将当前的workingMemory中的Message类型的Fact对象进行属性更新,这种操作会触发规则的重新匹配执行,可以理解为Fact对象更新了,所以规则需要重新匹配一遍,那么疑问是之前规则执行过并且修改过的那些Fact对象的属性的数据会不会被重置?结果是不会,已经修改过了就不会被重置,update之后,之前的修改都会生效。当然对Fact对象数据的修改并不是一定需要调用update才可以生效,简单的使用set方法设置就可以完成,这里类似于java的引用调用,所以何时使用update是一个需要仔细考虑的问题,一旦不慎,极有可能会造成规则的死循环。上述的no-loop true,即设置当前的规则,只执行一次,如果本身的RHS部分有update等触发规则重新执行的操作,也不要再次执行当前规则。

但是其他的规则会被重新执行,岂不是也会有可能造成多次重复执行,数据紊乱甚至死循环?答案是使用其他的标签限制,也是可以控制的:lock-on-active true

lock-on-active true:通过这个标签,可以控制当前的规则只会被执行一次,因为一个规则的重复执行不一定是本身触发的,也可能是其他规则触发的,所以这个是no-loop的加强版。当然该标签正规的用法会有其他的标签的配合,后续提及。

date-expires:设置规则的过期时间,默认的时间格式:“日-月-年”,中英文格式相同,但是写法要用各自对应的语言,比如中文:"29-七月-2010",但是还是推荐使用更为精确和习惯的格式,这需要手动在java代码中设置当前系统的时间格式,后续提及。属性用法举例:date-expires "2011-01-31 23:59:59" // 这里我们使用了更为习惯的时间格式

date-effective:设置规则的生效时间,时间格式同上。

duration:规则定时,duration 3000   3秒后执行规则

salience:优先级,数值越大越先执行,这个可以控制规则的执行顺序。

其他的属性可以参照相关的api文档查看具体用法,此处略。

规则的条件部分,即LHS部分:

when:规则条件开始。条件可以单个,也可以多个,多个条件一次排列,比如

when

eval(true)

$customer:Customer()

$message:Message(status==0)

上述罗列了三个条件,当前规则只有在这三个条件都匹配的时候才会执行RHS部分,三个条件中第一个

eval(true):是一个默认的api,true 无条件执行,类似于 while(true)

$message:Message(status==0) 这句话标示的:当前的workingMemory存在Message类型并且status属性的值为0的Fact对象,这个对象通常是通过外部java代码插入或者自己在前面已经执行的规则的RHS部分中insert进去的。

前面的$message代表着当前条件的引用变量,在后续的条件部分和RHS部分中,可以使用当前的变量去引用符合条件的FACT对象,修改属性或者调用方法等。可选,如果不需要使用,则可以不写。

条件可以有组合,比如:

Message(status==0 || (status > 1 && status <=100))

RHS中对Fact对象private属性的操作必须使用getter和setter方法,而RHS中则必须要直接用.的方法去使用,比如

$order:Order(name=="qu")
  $message:Message(status==0 && orders contains $order && $order.name=="qu")

特别的是,如果条件全部是 &&关系,可以使用“,”来替代,但是两者不能混用

如果现在Fact对象中有一个List,需要判断条件,如何判断呢?

看一个例子:

Message {

int status;

List names;

}

$message:Message(status==0 && names contains "网易" && names.size >= 1)

上述的条件中,status必须是0,并且names列表中含有“网易”并且列表长度大于等于1

contains:对比是否包含操作,操作的被包含目标可以是一个复杂对象也可以是一个简单的值。

Drools提供了十二中类型比较操作符:

>  >=  <  <=  ==  !=  contains / not contains / memberOf / not memberOf /matches/ not matches

not contains:与contains相反。

memberOf:判断某个Fact属性值是否在某个集合中,与contains不同的是他被比较的对象是一个集合,而contains被比较的对象是单个值或者对象。

not memberOf:正好相反。

matches:正则表达式匹配,与java不同的是,不用考虑'/'的转义问题

not matches:正好相反。

规则的结果部分

当规则条件满足,则进入规则结果部分执行,结果部分可以是纯java代码,比如:

then

System.out.println("OK"); //会在控制台打印出ok

end

当然也可以调用Fact的方法,比如  $message.execute();操作数据库等等一切操作。

结果部分也有drools提供的方法:

insert:往当前workingMemory中插入一个新的Fact对象,会触发规则的再次执行,除非使用no-loop限定;

update:更新

modify:修改,与update语法不同,结果都是更新操作

retract:删除

RHS部分除了调用Drools提供的api和Fact对象的方法,也可以调用规则文件中定义的方法,方法的定义使用 function 关键字

function void console {

System.out.println();

StringUtils.getId();// 调用外部静态方法,StringUtils必须使用import导入,getId()必须是静态方法

}

Drools还有一个可以定义类的关键字:

declare 可以再规则文件中定义一个class,使用起来跟普通java对象相似,你可以在RHS部分中new一个并且使用getter和setter方法去操作其属性。

declare Address
 @author(quzishen) // 元数据,仅用于描述信息

@createTime(2011-1-24)
 city : String @maxLengh(100)
 postno : int
end

上述的'@'是什么呢?是元数据定义,用于描述数据的数据~,没什么执行含义

你可以在RHS部分中使用Address address = new Address()的方法来定义一个对象。

更多的规则语法,可以参考其他互联网资料,推荐:

http://wenku.baidu.com/view/a6516373f242336c1eb95e7c.html

(写的很基础,但是部分语法写的有些简单,含糊不好理解)

2、Drools应用实例:

现在我们模拟一个应用场景:网站伴随业务产生而进行的积分发放操作。比如支付宝信用卡还款奖励积分等。

发放积分可能伴随不同的运营策略和季节性调整,发放数目和规则完全不同,如果使用硬编码的方式去伴随业务调整而修改,代码的修改、管理、优化、测试、上线将是一件非常麻烦的事情,所以,将发放规则部分提取出来,交给Drools管理,可以极大程度的解决这个问题。

(注意一点的是,并非所有的规则相关内容都建议使用Drools,这其中要考虑系统会运行多久,规则变更频率等一系列条件,如果你的系统只会在线上运行一周,那根本没必要选择Drools来加重你的开发成本,java硬编码的方式则将是首选)

我们定义一下发放规则:

积分的发放参考因素有:交易笔数、交易金额数目、信用卡还款次数、生日特别优惠等。

定义规则:

// 过生日,则加10分,并且将当月交易比数翻倍后再计算积分

// 2011-01-08 - 2011-08-08每月信用卡还款3次以上,每满3笔赠送30分

// 当月购物总金额100以上,每100元赠送10分

// 当月购物次数5次以上,每五次赠送50分

// 特别的,如果全部满足了要求,则额外奖励100分

// 发生退货,扣减10分

// 退货金额大于100,扣减100分

在事先分析过程中,我们需要全面的考虑对于积分所需要的因素,以此整理抽象Fact对象,通过上述的假设条件,我们假设积分计算对象如下:

[java] view plain copy
  1. /**
  2. * 积分计算对象
  3. * @author quzishen
  4. */
  5. publicclass PointDomain {
  6. // 用户名
  7. private String userName;
  8. // 是否当日生日
  9. privateboolean birthDay;
  10. // 增加积分数目
  11. privatelong point;
  12. // 当月购物次数
  13. privateint buyNums;
  14. // 当月退货次数
  15. privateint backNums;
  16. // 当月购物总金额
  17. privatedouble buyMoney;
  18. // 当月退货总金额
  19. privatedouble backMondy;
  20. // 当月信用卡还款次数
  21. privateint billThisMonth;
  22. /**
  23. * 记录积分发送流水,防止重复发放
  24. * @param userName 用户名
  25. * @param type 积分发放类型
  26. */
  27. publicvoid recordPointLog(String userName, String type){
  28. System.out.println("增加对"+userName+"的类型为"+type+"的积分操作记录.");
  29. }
  30. public String getUserName() {
  31. return userName;
  32. }
  33. // 其他getter setter方法省略
  34. }

定义积分规则接口

[java] view plain copy

 
  1. /**
  2. * 规则接口
  3. * @author quzishen
  4. */
  5. publicinterface PointRuleEngine {
  6. /**
  7. * 初始化规则引擎
  8. */
  9. publicvoid initEngine();
  10. /**
  11. * 刷新规则引擎中的规则
  12. */
  13. publicvoid refreshEnginRule();
  14. /**
  15. * 执行规则引擎
  16. * @param pointDomain 积分Fact
  17. */
  18. publicvoid executeRuleEngine(final PointDomain pointDomain);
  19. }

规则接口实现,Drools的API很简单,可以参考相关API文档查看具体用法:

[java] view plain copy
  1. import java.io.File;
  2. import java.io.FileNotFoundException;
  3. import java.io.FileReader;
  4. import java.io.IOException;
  5. import java.io.Reader;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import org.drools.RuleBase;
  9. import org.drools.StatefulSession;
  10. import org.drools.compiler.DroolsParserException;
  11. import org.drools.compiler.PackageBuilder;
  12. import org.drools.spi.Activation;
  13. /**
  14. * 规则接口实现类
  15. * @author quzishen
  16. */
  17. publicclass PointRuleEngineImpl implements PointRuleEngine {
  18. private RuleBase ruleBase;
  19. /* (non-Javadoc)
  20. * @see com.drools.demo.point.PointRuleEngine#initEngine()
  21. */
  22. publicvoid initEngine() {
  23. // 设置时间格式
  24. System.setProperty("drools.dateformat", "yyyy-MM-dd HH:mm:ss");
  25. ruleBase = RuleBaseFacatory.getRuleBase();
  26. try {
  27. PackageBuilder backageBuilder = getPackageBuilderFromDrlFile();
  28. ruleBase.addPackages(backageBuilder.getPackages());
  29. } catch (DroolsParserException e) {
  30. e.printStackTrace();
  31. } catch (IOException e) {
  32. e.printStackTrace();
  33. } catch (Exception e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. /* (non-Javadoc)
  38. * @see com.drools.demo.point.PointRuleEngine#refreshEnginRule()
  39. */
  40. publicvoid refreshEnginRule() {
  41. ruleBase = RuleBaseFacatory.getRuleBase();
  42. org.drools.rule.Package[] packages = ruleBase.getPackages();
  43. for(org.drools.rule.Package pg : packages) {
  44. ruleBase.removePackage(pg.getName());
  45. }
  46. initEngine();
  47. }
  48. /* (non-Javadoc)
  49. * @see com.drools.demo.point.PointRuleEngine#executeRuleEngine(com.drools.demo.point.PointDomain)
  50. */
  51. publicvoid executeRuleEngine(final PointDomain pointDomain) {
  52. if(null == ruleBase.getPackages() || 0 == ruleBase.getPackages().length) {
  53. return;
  54. }
  55. StatefulSession statefulSession = ruleBase.newStatefulSession();
  56. statefulSession.insert(pointDomain);
  57. // fire
  58. statefulSession.fireAllRules(new org.drools.spi.AgendaFilter() {
  59. publicboolean accept(Activation activation) {
  60. return !activation.getRule().getName().contains("_test");
  61. }
  62. });
  63. statefulSession.dispose();
  64. }
  65. /**
  66. * 从Drl规则文件中读取规则
  67. * @return
  68. * @throws Exception
  69. */
  70. private PackageBuilder getPackageBuilderFromDrlFile() throws Exception {
  71. // 获取测试脚本文件
  72. List  drlFilePath = getTestDrlFile();
  73. // 装载测试脚本文件
  74. List  readers = readRuleFromDrlFile(drlFilePath);
  75. PackageBuilder backageBuilder = new PackageBuilder();
  76. for (Reader r : readers) {
  77. backageBuilder.addPackageFromDrl(r);
  78. }
  79. // 检查脚本是否有问题
  80. if(backageBuilder.hasErrors()) {
  81. thrownew Exception(backageBuilder.getErrors().toString());
  82. }
  83. return backageBuilder;
  84. }
  85. /**
  86. * @param drlFilePath 脚本文件路径
  87. * @return
  88. * @throws FileNotFoundException
  89. */
  90. private List  readRuleFromDrlFile(List  drlFilePath)  throws FileNotFoundException {
  91. if (null == drlFilePath || 0 == drlFilePath.size()) {
  92. returnnull;
  93. }
  94. List  readers =  new  ArrayList ();
  95. for (String ruleFilePath : drlFilePath) {
  96. readers.add(new FileReader(new File(ruleFilePath)));
  97. }
  98. return readers;
  99. }
  100. /**
  101. * 获取测试规则文件
  102. *
  103. * @return
  104. */
  105. private List  getTestDrlFile() {
  106. List  drlFilePath =  new  ArrayList ();
  107. drlFilePath
  108. .add("D:/workspace2/DroolsDemo/src/com/drools/demo/point/addpoint.drl");
  109. drlFilePath
  110. .add("D:/workspace2/DroolsDemo/src/com/drools/demo/point/subpoint.drl");
  111. return drlFilePath;
  112. }
  113. }

为了获取单实例的RuleBase,我们定义一个工厂类

[java] view plain copy

 
  1. import org.drools.RuleBase;
  2. import org.drools.RuleBaseFactory;
  3. /**
  4. * RuleBaseFacatory 单实例RuleBase生成工具
  5. * @author quzishen
  6. */
  7. publicclass RuleBaseFacatory {
  8. privatestatic RuleBase ruleBase;
  9. publicstatic RuleBase getRuleBase(){
  10. returnnull != ruleBase ? ruleBase : RuleBaseFactory.newRuleBase();
  11. }
  12. }

剩下的就是定义两个规则文件,分别用于积分发放和积分扣减

addpoint.drl

[java] view plain copy
  1. package com.drools.demo.point
  2. import com.drools.demo.point.PointDomain;
  3. rule birthdayPoint
  4. // 过生日,则加10分,并且将当月交易比数翻倍后再计算积分
  5. salience 100
  6. lock-on-active true
  7. when
  8. $pointDomain : PointDomain(birthDay == true)
  9. then
  10. $pointDomain.setPoint($pointDomain.getPoint()+10);
  11. $pointDomain.setBuyNums($pointDomain.getBuyNums()*2);
  12. $pointDomain.setBuyMoney($pointDomain.getBuyMoney()*2);
  13. $pointDomain.setBillThisMonth($pointDomain.getBillThisMonth()*2);
  14. $pointDomain.recordPointLog($pointDomain.getUserName(),"birthdayPoint");
  15. end
  16. rule billThisMonthPoint
  17. // 2011-01-08 - 2011-08-08每月信用卡还款3次以上,每满3笔赠送30分
  18. salience 99
  19. lock-on-active true
  20. date-effective "2011-01-08 23:59:59"
  21. date-expires "2011-08-08 23:59:59"
  22. when
  23. $pointDomain : PointDomain(billThisMonth >= 3)
  24. then
  25. $pointDomain.setPoint($pointDomain.getPoint()+$pointDomain.getBillThisMonth()/3*30);
  26. $pointDomain.recordPointLog($pointDomain.getUserName(),"billThisMonthPoint");
  27. end
  28. rule buyMoneyPoint
  29. // 当月购物总金额100以上,每100元赠送10分
  30. salience 98
  31. lock-on-active true
  32. when
  33. $pointDomain : PointDomain(buyMoney >= 100)
  34. then
  35. $pointDomain.setPoint($pointDomain.getPoint()+ (int)$pointDomain.getBuyMoney()/100 * 10);
  36. $pointDomain.recordPointLog($pointDomain.getUserName(),"buyMoneyPoint");
  37. end
  38. rule buyNumsPoint
  39. // 当月购物次数5次以上,每五次赠送50分
  40. salience 97
  41. lock-on-active true
  42. when
  43. $pointDomain : PointDomain(buyNums >= 5)
  44. then
  45. $pointDomain.setPoint($pointDomain.getPoint()+$pointDomain.getBuyNums()/5 * 50);
  46. $pointDomain.recordPointLog($pointDomain.getUserName(),"buyNumsPoint");
  47. end
  48. rule allFitPoint
  49. // 特别的,如果全部满足了要求,则额外奖励100分
  50. salience 96
  51. lock-on-active true
  52. when
  53. $pointDomain:PointDomain(buyNums >= 5 && billThisMonth >= 3 && buyMoney >= 100)
  54. then
  55. $pointDomain.setPoint($pointDomain.getPoint()+ 100);
  56. $pointDomain.recordPointLog($pointDomain.getUserName(),"allFitPoint");
  57. end

subpoint.drl

[java] view plain copy

 
  1. package com.drools.demo.point
  2. import com.drools.demo.point.PointDomain;
  3. rule subBackNumsPoint
  4. // 发生退货,扣减10分
  5. salience 10
  6. lock-on-active true
  7. when
  8. $pointDomain : PointDomain(backNums >= 1)
  9. then
  10. $pointDomain.setPoint($pointDomain.getPoint()-10);
  11. $pointDomain.recordPointLog($pointDomain.getUserName(),"subBackNumsPoint");
  12. end
  13. rule subBackMondyPoint
  14. // 退货金额大于100,扣减100分
  15. salience 9
  16. lock-on-active true
  17. when
  18. $pointDomain : PointDomain(backMondy >= 100)
  19. then
  20. $pointDomain.setPoint($pointDomain.getPoint()-10);
  21. $pointDomain.recordPointLog($pointDomain.getUserName(),"subBackMondyPoint");
  22. end

测试方法:

[java] view plain copy
  1. publicstaticvoid main(String[] args) throws IOException {
  2. PointRuleEngine pointRuleEngine = new PointRuleEngineImpl();
  3. while(true){
  4. InputStream is = System.in;
  5. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  6. String input = br.readLine();
  7. if(null != input && "s".equals(input)){
  8. System.out.println("初始化规则引擎...");
  9. pointRuleEngine.initEngine();
  10. System.out.println("初始化规则引擎结束.");
  11. }elseif("e".equals(input)){
  12. final PointDomain pointDomain = new PointDomain();
  13. pointDomain.setUserName("hello kity");
  14. pointDomain.setBackMondy(100d);
  15. pointDomain.setBuyMoney(500d);
  16. pointDomain.setBackNums(1);
  17. pointDomain.setBuyNums(5);
  18. pointDomain.setBillThisMonth(5);
  19. pointDomain.setBirthDay(true);
  20. pointDomain.setPoint(0l);
  21. pointRuleEngine.executeRuleEngine(pointDomain);
  22. System.out.println("执行完毕BillThisMonth:"+pointDomain.getBillThisMonth());
  23. System.out.println("执行完毕BuyMoney:"+pointDomain.getBuyMoney());
  24. System.out.println("执行完毕BuyNums:"+pointDomain.getBuyNums());
  25. System.out.println("执行完毕规则引擎决定发送积分:"+pointDomain.getPoint());
  26. } elseif("r".equals(input)){
  27. System.out.println("刷新规则文件...");
  28. pointRuleEngine.refreshEnginRule();
  29. System.out.println("刷新规则文件结束.");
  30. }
  31. }
  32. }

执行结果:

-----------------

增加对hello kity的类型为birthdayPoint的积分操作记录.
增加对hello kity的类型为billThisMonthPoint的积分操作记录.
增加对hello kity的类型为buyMoneyPoint的积分操作记录.
增加对hello kity的类型为buyNumsPoint的积分操作记录.
增加对hello kity的类型为allFitPoint的积分操作记录.
增加对hello kity的类型为subBackNumsPoint的积分操作记录.
增加对hello kity的类型为subBackMondyPoint的积分操作记录.
执行完毕BillThisMonth:10
执行完毕BuyMoney:1000.0
执行完毕BuyNums:10
执行完毕规则引擎决定发送积分:380

JAVA规则引擎 -- Drools的更多相关文章

  1. [Drools]JAVA规则引擎 -- Drools 2

    上一篇文章 http://blog.csdn.net/quzishen/archive/2011/01/25/6163012.aspx 描述了一些常用的drools的语法标签和一个模拟实例即发送积分的 ...

  2. [Drools]JAVA规则引擎 -- Drools

    Drools是一个基于Java的规则引擎,开源的,可以将复杂多变的规则从硬编码中解放出来,以规则脚本的形式存放在文件中,使得规则的变更不需要修正代码重启机器就可以立即在线上环境生效. 本文所使用的de ...

  3. Java规则引擎drools:drt动态生成规则并附上具体项目逻辑

    一 整合 由于本人的码云太多太乱了,于是决定一个一个的整合到一个springboot项目里面. 附上自己的项目地址https://github.com/247292980/spring-boot 以整 ...

  4. [Drools]JAVA规则引擎 -- Drools- 转http://blog.csdn.net/quzishen/article/details/6163012

    [Drools]JAVA规则引擎 -- Drools 标签: java引擎exceptiongetterstringsetter 2011-01-25 14:33 113340人阅读 评论(35) 收 ...

  5. JAVA规则引擎JSR-94笔札

    JAVA规则引擎JSR-94笔札 JSR-94 是由JCP(Java Community Process)组织所制定的java规则引擎API的java请求规范.它主要定义了规则引擎在java运行时的一 ...

  6. Java规则引擎及JSR-94[转]

      规则引擎简介 Java规则引擎是推理引擎的一种,它起源于基于规则的专家系统.       Java规则引擎将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策.Java规则引擎接 ...

  7. 【java规则引擎】之规则引擎解释

    转载:http://www.open-open.com/lib/view/open1417528754230.html 现实生活中,规则无处不在.法律.法规和各种制度均是:对于企业级应用来说,在IT技 ...

  8. 开源规则引擎 drools

    java语言开发的开源业务规则引擎 DROOLS(JBOSS RULES )具有一个易于访问企业策略.易于调整以及易于管理的开源业务规则引擎,符合业内标准,速度快.效率高.业务分析师或审核人员可以利用 ...

  9. 规则引擎drools封装

    一.前言 网上规则引擎drools介绍很多,并且有很多细致的说明,作者也不敢托大说自己的好用,但作者经过2个项目使用过规则引擎后,自己对规则引擎的理解并进行封装,对规则内容及如何使用,有自己的一番实践 ...

随机推荐

  1. (转)Linux进程间通信

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 谢谢nonoob纠错 我们在Linux信号基础中已经说明,信号可以看作一种粗糙的进 ...

  2. Shell实现跳板机,为什么用跳板机

    整理自:http://blog.chinaunix.net/uid-22101889-id-3167454.html 注意:请谨慎使用,到现在为止,使用了,我还没找到改回去的方法. 1.     问题 ...

  3. Lock wait timeout exceeded; try restarting transaction

    What gives this away is the word transaction. It is evident by the statement that the query was atte ...

  4. HDU4003 Find Metal Mineral 树形DP

    Find Metal Mineral Problem Description Humans have discovered a kind of new metal mineral on Mars wh ...

  5. cellspacing与cellpadding

    此文引用自cellpadding和cellspacing属性来控制表格边框的间距. 作者:nestea 巢(cell) -- 表格的内容 巢补白(表格填充)(cellpadding) -- 代表巢外面 ...

  6. Java 获取本机IP

    import java.io.*; import java.util.*; import java.net.*; public class GetIP { public static void mai ...

  7. OSX Mavericks下使用Synergy进行多台主机通过wifi共享键鼠问题的解决方法

    转帖: OSX 10.9 几天用下来还是遇到几处问题的:之前先是遇到了OSX Mavericks GM598无法从Appstore升级到完全正式版的问题,下载无反应,后来找到了解决方法,发在以下链接: ...

  8. Delphi是座宝山,有待挖掘

    Delphi是座宝山,有待挖掘1. VCL源码是座宝山,把纷繁复杂的Windows编程封装到短短几个类里,不超过8000行代码,还额外包括许多其它的技巧2. RTL是座宝山,方便程序员使用底层运算,不 ...

  9. Spring整合JUnit4测试

    @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"classpath:spring/ap ...

  10. Two Sigma OA

    刚做了两道Two Sigma OA. 还是两道老题, Friend Cycle和Longest Chain. Friend Cycle可以用Union Find来做.优化的时候因为矩阵是沿对角线对称, ...