Commit 56b9c321e04c5631a015dba1f06edfcf35a14560

Authored by 徐烜
1 parent d0dedf6e

排班计划修正

1、将排班计划的主要逻辑封装成DroolsSchedulePlan类
2、在主SchedulePlanServiceImpl中添加ReentrantLock锁,控制相同线路并发生成计划
src/main/java/com/bsth/service/schedule/impl/SchedulePlanServiceImpl.java
1 1 package com.bsth.service.schedule.impl;
2 2  
3   -import com.bsth.entity.Line;
4 3 import com.bsth.entity.schedule.SchedulePlan;
5   -import com.bsth.entity.schedule.SchedulePlanInfo;
6 4 import com.bsth.entity.schedule.TTInfo;
7   -import com.bsth.entity.schedule.rule.ScheduleRule1Flat;
8 5 import com.bsth.repository.BusinessRepository;
9 6 import com.bsth.repository.LineRepository;
10 7 import com.bsth.repository.schedule.*;
11 8 import com.bsth.service.schedule.SchedulePlanService;
12 9 import com.bsth.service.schedule.exception.ScheduleException;
  10 +import com.bsth.service.schedule.plan.DroolsSchedulePlan;
13 11 import com.bsth.service.schedule.rules.ScheduleRuleService;
14   -import com.bsth.service.schedule.rules.plan.PlanCalcuParam_input;
15   -import com.bsth.service.schedule.rules.plan.PlanResult;
16   -import com.bsth.service.schedule.rules.rerun.RerunRule_input;
17   -import com.bsth.service.schedule.rules.rerun.RerunRule_param;
18   -import com.bsth.service.schedule.rules.shiftloop.ScheduleCalcuParam_input;
19   -import com.bsth.service.schedule.rules.shiftloop.ScheduleResults_output;
20   -import com.bsth.service.schedule.rules.shiftloop.ScheduleRule_input;
21   -import com.bsth.service.schedule.rules.ttinfo.*;
22 12 import com.bsth.service.schedule.rules.ttinfo2.CalcuParam;
23 13 import com.bsth.service.schedule.rules.ttinfo2.Result;
24   -import com.bsth.service.schedule.rules.validate.ValidateParam;
25   -import com.bsth.service.schedule.rules.validate.ValidateResults_output;
26   -import org.apache.commons.lang3.StringUtils;
27 14 import org.joda.time.DateTime;
28 15 import org.kie.api.KieBase;
29 16 import org.kie.api.runtime.KieSession;
... ... @@ -37,6 +24,9 @@ import org.springframework.transaction.annotation.Propagation;
37 24 import org.springframework.transaction.annotation.Transactional;
38 25  
39 26 import java.util.*;
  27 +import java.util.concurrent.ConcurrentHashMap;
  28 +import java.util.concurrent.TimeUnit;
  29 +import java.util.concurrent.locks.ReentrantLock;
40 30  
41 31 /**
42 32 * Created by xu on 16/6/16.
... ... @@ -44,12 +34,12 @@ import java.util.*;
44 34 @Service
45 35 public class SchedulePlanServiceImpl extends BServiceImpl<SchedulePlan, Long> implements SchedulePlanService {
46 36 @Autowired
47   - @Qualifier("kb1")
48   - private KieBase kieBase;
  37 + @Qualifier("coreKBase")
  38 + private KieBase coreKBase;
49 39  
50 40 @Autowired
51   - @Qualifier("kb2")
52   - private KieBase kieBase2;
  41 + @Qualifier("preKBase")
  42 + private KieBase preKBase;
53 43  
54 44 @Autowired
55 45 private ScheduleRule1FlatRepository scheduleRule1FlatRepository;
... ... @@ -73,398 +63,62 @@ public class SchedulePlanServiceImpl extends BServiceImpl&lt;SchedulePlan, Long&gt; im
73 63 /** 日志记录器 */
74 64 private Logger logger = LoggerFactory.getLogger(SchedulePlanServiceImpl.class);
75 65  
76   - /**
77   - * 计算规则输入。
78   - * @param schedulePlan
79   - * @return
80   - */
81   - private List<ScheduleRule_input> calcuSrfList(SchedulePlan schedulePlan) {
82   - // 1-1、构造drools规则输入数据,输出数据
83   - // 全局计算参数
84   - ScheduleCalcuParam_input scheduleCalcuParam_input = new ScheduleCalcuParam_input(schedulePlan);
85   -
86   - // 规则输出数据
87   - List<ScheduleRule_input> scheduleRule_inputs = new ArrayList<>();
88   -
89   - // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
90   - // 创建session,内部配置的是stateful
91   - KieSession session = kieBase2.newKieSession();
92   - // 设置gloable对象,在drl中通过别名使用
93   - session.setGlobal("sriList", scheduleRule_inputs);
94   - session.setGlobal("log", logger); // 设置日志
95   -
96   - session.setGlobal("srf", scheduleRule1FlatRepository);
97   - session.setGlobal("rrr", rerunRuleRepository);
98   - session.setGlobal("srservice", scheduleRuleService);
99   -
100   - // 载入数据
101   - session.insert(scheduleCalcuParam_input);
102   -
103   - // 执行rule
104   - session.fireAllRules();
105   -
106   - // 执行完毕销毁,有日志的也要关闭
107   - session.dispose();
108   -
109   - return scheduleRule_inputs;
110   - }
111   -
112   - /**
113   - * 循环规则输出。
114   - * @param schedulePlan 排班计划对象
115   - * @param lpInfoResults_output 时刻表每日路牌的情况
116   - */
117   - private ScheduleResults_output loopRuleOutput(
118   - SchedulePlan schedulePlan,
119   - LpInfoResults_output lpInfoResults_output) {
120   - // 1-1、构造drools规则输入数据,输出数据
121   - // 全局计算参数
122   - ScheduleCalcuParam_input scheduleCalcuParam_input = new ScheduleCalcuParam_input(schedulePlan);
123   - // 每个规则对应的输入参数
124   - List<ScheduleRule_input> scheduleRule_inputs = calcuSrfList(schedulePlan);
125   -
126   - // 规则输出数据
127   - ScheduleResults_output scheduleResults_output = new ScheduleResults_output();
128   -
129   - // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
130   - // 创建session,内部配置的是stateful
131   - KieSession session = kieBase.newKieSession();
132   - // 设置gloable对象,在drl中通过别名使用
133   - session.setGlobal("scheduleResult", scheduleResults_output);
134   - session.setGlobal("log", logger); // 设置日志
135   - session.setGlobal("scheduleRuleService", scheduleRuleService);
136   -
137   - // 载入数据
138   - session.insert(scheduleCalcuParam_input);
139   - for (ScheduleRule_input scheduleRule_input : scheduleRule_inputs) {
140   - session.insert(scheduleRule_input);
141   - }
142   - // 每日时刻表路牌数据
143   - for (LpInfoResult_output lpInfoResult_output: lpInfoResults_output.getLpInfoResult_outputs()) {
144   - session.insert(lpInfoResult_output);
145   - }
146   - // 执行rule
147   - session.fireAllRules();
148   -
149   - // 执行完毕销毁,有日志的也要关闭
150   - session.dispose();
151   -
152   - // 保存循环规则结果数据
153   - scheduleRuleService.generateRuleResult(scheduleResults_output.getSchedulePlanRuleResults());
154   -
155   -// logger.info("循环规则输出={}", scheduleResults_output.showGuideboardDesc1());
156   -
157   - return scheduleResults_output;
158   - }
159   -
160   - /**
161   - * 时刻表选择(判定每天使用的时刻表,以及路牌数据输出)。
162   - * @param schedulePlan 排班计划对象
163   - * @return TTInfoResults_output, LpInfoResults_output
164   - */
165   - private Object[] ttInfoOutput(SchedulePlan schedulePlan) {
166   - // 获取线路的所有未作废的时刻表
167   - List<TTInfo> ttInfos = ttInfoRepository.findInCanceledByXl(schedulePlan.getXl());
168   -
169   - // 1-1、构造drools规则输入数据,输出数据
170   - // 全局计算参数
171   - TTInfoCalcuParam_input ttInfoCalcuParam_input =
172   - new TTInfoCalcuParam_input(
173   - new DateTime(schedulePlan.getScheduleFromTime()),
174   - new DateTime(schedulePlan.getScheduleToTime()),
175   - String.valueOf(schedulePlan.getXl().getId())
176   - );
177   - // 规则输出数据
178   - TTInfoResults_output ttInfoResults_output = new TTInfoResults_output();
179   - LpInfoResults_output lpInfoResults_output = new LpInfoResults_output();
180   -
181   - // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
182   - // 创建session,内部配置的是stateful
183   - KieSession session = kieBase.newKieSession();
184   -
185   - // 设置gloable对象,在drl中通过别名使用
186   - session.setGlobal("results", ttInfoResults_output);
187   - session.setGlobal("lpInfoResults_output", lpInfoResults_output);
188   - session.setGlobal("log", logger); // 设置日志
189   - session.setGlobal("tTInfoDetailRepository", ttInfoDetailRepository);
190   -
191   - // 载入数据
192   - session.insert(ttInfoCalcuParam_input);
193   - for (TTInfo ttInfo : ttInfos) {
194   - TTInfo_input ttInfo_input = new TTInfo_input(ttInfo);
195   - session.insert(ttInfo_input);
196   - }
197   -
198   - // 载入数据2(计算规则最早启用时间)
199   - List<ScheduleRule1Flat> scheduleRule1Flats = scheduleRule1FlatRepository.findByXl(schedulePlan.getXl());
200   -
201   - for (ScheduleRule1Flat scheduleRule1Flat: scheduleRule1Flats) {
202   - ScheduleRule_input scheduleRule_input = new ScheduleRule_input(scheduleRule1Flat);
203   - session.insert(scheduleRule_input);
204   - }
205   -
206   - // 执行rule
207   - session.fireAllRules();
208   -
209   - // 执行完毕销毁,有日志的也要关闭
210   - session.dispose();
211   -
212   - return new Object[] {ttInfoResults_output, lpInfoResults_output};
213   -
214   - }
215   -
216   - /**
217   - * 排班生成。
218   - * @param schedulePlan 排班计划对象
219   - * @param scheduleResults_output loopRuleOutput方法规则输出
220   - * @param ttInfoResults_output ttInfoOutput方法规则输出
221   - * @return PlanResult
222   - */
223   - private PlanResult planResultOutput(
224   - SchedulePlan schedulePlan,
225   - ScheduleResults_output scheduleResults_output,
226   - TTInfoResults_output ttInfoResults_output) {
227   -
228   - // 1-1、构造drools规则输入数据,输出数据
229   - PlanCalcuParam_input planCalcuParam_input = new PlanCalcuParam_input(
230   - schedulePlan,
231   - scheduleResults_output,
232   - ttInfoResults_output
233   - );
234   - // 规则输出数据
235   - PlanResult planResult = new PlanResult();
236   - planResult.setXlId(schedulePlan.getXl().getId().toString());
237   -
238   - // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
239   - // 创建session,内部配置的是stateful
240   - KieSession session = kieBase.newKieSession();
241   -
242   - // 设置gloable对象,在drl中通过别名使用
243   - session.setGlobal("planResult", planResult);
244   - session.setGlobal("log", logger); // 设置日志
245   -
246   - session.setGlobal("tTInfoDetailRepository", ttInfoDetailRepository);
247   - session.setGlobal("carConfigInfoRepository", carConfigInfoRepository);
248   - session.setGlobal("employeeConfigInfoRepository", employeeConfigInfoRepository);
249   - session.setGlobal("lineRepository", lineRepository);
250   - session.setGlobal("businessRepository", businessRepository);
251   -
252   - // 载入数据
253   - session.insert(planCalcuParam_input);
254   -
255   - // 执行rule
256   - session.fireAllRules();
257   -
258   - // 执行完毕销毁,有日志的也要关闭
259   - session.dispose();
260   -
261   - return planResult;
262   -
263   - }
264   -
265   - /**
266   - * 生成线路排班(不含套跑规则)。
267   - * @param schedulePlan
268   - * @return
269   - */
270   - private PlanResult schedulePlanWithOutRerun(SchedulePlan schedulePlan) {
271   - // 1、时刻表数据及每日路牌数据计算
272   - Date start1 = new Date();
273   - Object[] ttInfoRets = ttInfoOutput(schedulePlan);
274   - TTInfoResults_output ttInfoResults_output = (TTInfoResults_output) ttInfoRets[0];
275   - LpInfoResults_output lpInfoResults_output = (LpInfoResults_output) ttInfoRets[1];
276   - Date end1 = new Date();
277   - // 2、循环规则计算输出
278   - Date start2 = new Date();
279   - ScheduleResults_output scheduleResults_output = loopRuleOutput(schedulePlan, lpInfoResults_output);
280   - Date end2 = new Date();
281   -
282   - logger.info("规则计算结果={}", scheduleResults_output.showGuideboardDesc1());
283   -
284   - // 3、计划输出
285   - Date start3 = new Date();
286   - PlanResult planResult = planResultOutput(schedulePlan, scheduleResults_output, ttInfoResults_output);
287   - Date end3 = new Date();
288   -
289   - logger.info("drool时刻表每日路牌计算 {} ms,drool循环规则计算 {} ms,drool计划数据 {} ms",
290   - end1.getTime() - start1.getTime(),
291   - end2.getTime() - start2.getTime(),
292   - end3.getTime() - start3.getTime());
293   -
294   - // TODO:将lpInfoResults_output 也要返回
295   -
296   - return planResult;
297   - }
298   -
299   - /**
300   - * 套跑计划排班数据。
301   - * @param planResult
302   - */
303   - private void rerunPlanResult(PlanResult planResult, SchedulePlan schedulePlan) {
304   - List<RerunRule_input> rerunRule_inputs = scheduleRuleService.findRerunrule(Integer.parseInt(planResult.getXlId()));
305   - logger.info("套跑数量 {} 组", rerunRule_inputs.size());
306   -
307   - // 主线路id
308   - Integer mainXlId = schedulePlan.getXl().getId();
309   -
310   - if (rerunRule_inputs.size() > 0) {
311   - // 找出是对应路牌类型的线路,计算循环规则输出
312   - Set<String> xlids = new HashSet<>();
313   - for (RerunRule_input rerunRule_input: rerunRule_inputs) {
314   - if ("dylp".equals(rerunRule_input.getType())) {
315   - xlids.add(rerunRule_input.getS_xl()); // 参与套跑的线路
316   - }
317   - }
318   -
319   - List<ScheduleResults_output> scheduleResults_outputs = new ArrayList<>();
320   - Date start1 = new Date();
321   - for (String xlid: xlids) {
322   - schedulePlan.getXl().setId(Integer.parseInt(xlid)); // 套跑的线路默认跟着主线路设定走
323   - // 获取套跑线路的循环规则计算输出
324   - Object[] ttInfoRets = ttInfoOutput(schedulePlan);
325   - LpInfoResults_output lpInfoResults_output = (LpInfoResults_output) ttInfoRets[1];
326   - ScheduleResults_output scheduleResults_output = loopRuleOutput(schedulePlan, lpInfoResults_output);
327   - scheduleResults_outputs.add(scheduleResults_output);
328   - }
329   -
330   - // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
331   - // 创建session,内部配置的是stateful
332   - KieSession session = kieBase.newKieSession();
333   -
334   - // 设置gloable对象,在drl中通过别名使用
335   - session.setGlobal("planResult", planResult);
336   - session.setGlobal("log", logger); // 设置日志
337   -
338   - session.setGlobal("carConfigInfoRepository", carConfigInfoRepository);
339   - session.setGlobal("employeeConfigInfoRepository", employeeConfigInfoRepository);
340   -
341   - // 载入数据
342   - RerunRule_param rerunRule_param = new RerunRule_param();
343   - rerunRule_param.setMxlid(planResult.getXlId());
344   - rerunRule_param.setXlIds_dylp(xlids);
345   - session.insert(rerunRule_param);
346   - for (RerunRule_input rri: rerunRule_inputs) {
347   - session.insert(rri);
348   - }
349   - for (SchedulePlanInfo spi: planResult.getSchedulePlanInfos()) {
350   - session.insert(spi);
  66 + /** 线路独占锁 */
  67 + private ConcurrentHashMap<Integer, ReentrantLock> lineXLatchMaps = new ConcurrentHashMap<>();
  68 + private ReentrantLock getLineXLatch(Integer xlid) {
  69 + ReentrantLock lineXLatch = lineXLatchMaps.get(xlid);
  70 + if (lineXLatch == null) {
  71 + lineXLatch = new ReentrantLock();
  72 + ReentrantLock pre = lineXLatchMaps.putIfAbsent(xlid, lineXLatch);
  73 + if (pre != null) {
  74 + lineXLatch = pre;
351 75 }
352   - for (ScheduleResults_output sro: scheduleResults_outputs) {
353   - session.insert(sro);
354   - }
355   -
356   - // 执行rule
357   - session.fireAllRules();
358   -
359   - // 执行完毕销毁,有日志的也要关闭
360   - session.dispose();
361   -
362   - Date end1 = new Date();
363   - logger.info("套跑规则计算,耗时 {} ms", end1.getTime() - start1.getTime());
364   -
365   - schedulePlan.getXl().setId(mainXlId);
366   -
367   - }
368   -
369   - }
370   -
371   - /**
372   - * 验证排班结果。
373   - * @param planResult
374   - * @param schedulePlan
375   - */
376   - public void validPlanResult(PlanResult planResult, SchedulePlan schedulePlan) {
377   - // 1-1、构造drools规则输入数据,输出数据
378   - ValidateParam validateParam = new ValidateParam(
379   - new DateTime(schedulePlan.getScheduleFromTime()),
380   - new DateTime(schedulePlan.getScheduleToTime())
381   - );
382   - // 规则输出数据
383   - ValidateResults_output result = new ValidateResults_output();
384   -
385   - // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
386   - // 创建session,内部配置的是stateful
387   - KieSession session = kieBase.newKieSession();
388   -
389   - // 设置gloable对象,在drl中通过别名使用
390   - session.setGlobal("validResult", result);
391   - session.setGlobal("log", logger); // 设置日志
392   -
393   - // 载入数据
394   - session.insert(validateParam);
395   - for (SchedulePlanInfo schedulePlanInfo: planResult.getSchedulePlanInfos()) {
396   - session.insert(schedulePlanInfo);
397   - }
398   -
399   - // 执行rule
400   - session.fireAllRules();
401   -
402   - // 执行完毕销毁,有日志的也要关闭
403   - session.dispose();
404   -
405   -// logger.info("错误总数={}", result.getInfos().size());
406   -// for (ValidateResults_output.ValidInfo validInfo: result.getInfos()) {
407   -// logger.info(validInfo.getDesc());
408   -// }
409   -
410   - // 取10条错误
411   - int size = result.getInfos().size() > 10 ? 10: result.getInfos().size();
412   - List<String> desclist = new ArrayList<>();
413   - for (int i = 0; i < size; i++) {
414   - desclist.add(result.getInfos().get(i).getDesc());
415   - }
416   - if (desclist.size() > 0) {
417   - schedulePlan.setPlanResult(StringUtils.join(desclist, "</br>"));
418   - } else {
419   - schedulePlan.setPlanResult("ok");
420 76 }
421   -
422   - // TODO:设定错误信息
  77 + return lineXLatch;
423 78 }
424 79  
425 80 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
426 81 public SchedulePlan save(SchedulePlan schedulePlan) {
427   - // pre、如果排班的数据之前已经有了,删除之前的数据
428   - Date startpre = new Date();
429   - scheduleRuleService.deleteSchedulePlanInfo(
430   - schedulePlan.getXl().getLineCode(),
431   - schedulePlan.getScheduleFromTime(),
432   - schedulePlan.getScheduleToTime());
433   - Date endpre = new Date();
434   -
435   - // 1、查找线路,这是主线路
436   - Line xl = lineRepository.findOne(schedulePlan.getXl().getId());
437   - logger.info("<--- 排班master线路 id={}, name={}, 开始排班", xl.getId(), xl.getName());
438   -
439   - // 2、确定主线路排班(包含完全套跑路牌规则,所谓完全套跑路牌规则指整个路牌的班次都是套跑规则指定的)
440   - PlanResult planResult = schedulePlanWithOutRerun(schedulePlan);
441   -
442   - // 3、确定套跑规则
443   - rerunPlanResult(planResult, schedulePlan);
444   -
445   - // TODO:3-1、验证排班结果
446   - validPlanResult(planResult, schedulePlan);
  82 + ReentrantLock lineXLatch = getLineXLatch(schedulePlan.getXl().getId());
  83 + try {
  84 + if (lineXLatch.tryLock(1, TimeUnit.SECONDS)) {
  85 + // pre、如果排班的数据之前已经有了,删除之前的数据
  86 + Date startPre = new Date();
  87 + scheduleRuleService.deleteSchedulePlanInfo(
  88 + schedulePlan.getXl().getLineCode(),
  89 + schedulePlan.getScheduleFromTime(),
  90 + schedulePlan.getScheduleToTime());
  91 + Date endPre = new Date();
  92 + logger.info("删除数据 {} ms --->", endPre.getTime() - startPre.getTime());
  93 +
  94 + // core、生成排班计划
  95 + DroolsSchedulePlan droolsSchedulePlan = new DroolsSchedulePlan(
  96 + schedulePlan,
  97 + lineRepository, scheduleRule1FlatRepository,
  98 + ttInfoRepository, ttInfoDetailRepository,
  99 + carConfigInfoRepository, employeeConfigInfoRepository,
  100 + rerunRuleRepository, businessRepository,
  101 + scheduleRuleService,
  102 + preKBase, coreKBase,
  103 + logger
  104 + );
  105 + droolsSchedulePlan.generatePlan();
447 106  
448   - // TODO:3-2、去除完全套跑遗漏班次(以后放到规则中执行)
449   - Iterator<SchedulePlanInfo> infoIterator = planResult.getSchedulePlanInfos().iterator();
450   - while (infoIterator.hasNext()) {
451   - SchedulePlanInfo schedulePlanInfo = infoIterator.next();
452   - if (schedulePlanInfo.getCl() == null) {
453   - infoIterator.remove();
  107 + return new SchedulePlan();
  108 + } else {
  109 + throw new ScheduleException("当前线路正在排班,请稍后再操作...");
454 110 }
455   - }
  111 + } catch (Exception exp) {
  112 + throw new RuntimeException(exp);
  113 + } finally {
  114 + try {
  115 + lineXLatch.unlock();
  116 + } catch (Exception exp2) {
456 117  
457   - // 4、保存数据(jdbcTemplate 批量插入)
458   - Date start4 = new Date();
459   - scheduleRuleService.generateSchedulePlan(schedulePlan, planResult.getSchedulePlanInfos());
460   - Date end4 = new Date();
  118 + }
461 119  
462   - logger.info("删除数据 {} ms,保存主线路数据 {} 条 耗时 {} ms --->",
463   - endpre.getTime() - startpre.getTime(),
464   - planResult.getSchedulePlanInfos().size(),
465   - end4.getTime() - start4.getTime());
  120 + }
466 121  
467   - return new SchedulePlan();
468 122 }
469 123  
470 124 @Override
... ... @@ -475,10 +129,12 @@ public class SchedulePlanServiceImpl extends BServiceImpl&lt;SchedulePlan, Long&gt; im
475 129 @Override
476 130 public SchedulePlan findSchedulePlanTommorw() {
477 131 DateTime today = new DateTime(new Date());
478   - DateTime tommorw = new DateTime(today.getYear(), today.getMonthOfYear(), today.getDayOfMonth(), 0, 0).plusDays(1);
  132 + DateTime tommorw = new DateTime(
  133 + today.getYear(), today.getMonthOfYear(),
  134 + today.getDayOfMonth(), 0, 0).plusDays(1);
479 135 Map<String, Object> param = new HashMap<>();
480 136 param.put("scheduleFromTime_le", tommorw.toDate());
481   - param.put("scheduleToTime_ge", tommorw.toDate() );
  137 + param.put("scheduleToTime_ge", tommorw.toDate());
482 138 Iterator<SchedulePlan> schedulePlanIterator = this.list(param).iterator();
483 139 if (schedulePlanIterator.hasNext()) {
484 140 return schedulePlanIterator.next();
... ... @@ -490,7 +146,7 @@ public class SchedulePlanServiceImpl extends BServiceImpl&lt;SchedulePlan, Long&gt; im
490 146 public Result validateTTInfo(Integer xlid, Date from, Date to) {
491 147 // 构造drools session->载入数据->启动规则->计算->销毁session
492 148 // 创建session,内部配置的是stateful
493   - KieSession session = kieBase.newKieSession();
  149 + KieSession session = coreKBase.newKieSession();
494 150 // 设置gloable对象,在drl中通过别名使用
495 151 session.setGlobal("log", logger);
496 152 session.setGlobal("lineRepository", lineRepository);
... ... @@ -513,7 +169,6 @@ public class SchedulePlanServiceImpl extends BServiceImpl&lt;SchedulePlan, Long&gt; im
513 169 // 执行完毕销毁,有日志的也要关闭
514 170 session.dispose();
515 171  
516   -
517 172 return rs;
518 173 }
519 174 }
... ...
src/main/java/com/bsth/service/schedule/plan/DroolsSchedulePlan.java 0 → 100644
  1 +package com.bsth.service.schedule.plan;
  2 +
  3 +import com.bsth.entity.Line;
  4 +import com.bsth.entity.schedule.SchedulePlan;
  5 +import com.bsth.entity.schedule.SchedulePlanInfo;
  6 +import com.bsth.entity.schedule.TTInfo;
  7 +import com.bsth.entity.schedule.rule.ScheduleRule1Flat;
  8 +import com.bsth.repository.BusinessRepository;
  9 +import com.bsth.repository.LineRepository;
  10 +import com.bsth.repository.schedule.*;
  11 +import com.bsth.service.schedule.rules.ScheduleRuleService;
  12 +import com.bsth.service.schedule.rules.plan.PlanCalcuParam_input;
  13 +import com.bsth.service.schedule.rules.plan.PlanResult;
  14 +import com.bsth.service.schedule.rules.rerun.RerunRule_input;
  15 +import com.bsth.service.schedule.rules.rerun.RerunRule_param;
  16 +import com.bsth.service.schedule.rules.shiftloop.ScheduleCalcuParam_input;
  17 +import com.bsth.service.schedule.rules.shiftloop.ScheduleResults_output;
  18 +import com.bsth.service.schedule.rules.shiftloop.ScheduleRule_input;
  19 +import com.bsth.service.schedule.rules.ttinfo.*;
  20 +import com.bsth.service.schedule.rules.validate.ValidateParam;
  21 +import com.bsth.service.schedule.rules.validate.ValidateResults_output;
  22 +import org.apache.commons.lang3.StringUtils;
  23 +import org.joda.time.DateTime;
  24 +import org.kie.api.KieBase;
  25 +import org.kie.api.runtime.KieSession;
  26 +import org.slf4j.Logger;
  27 +
  28 +import java.util.*;
  29 +
  30 +/**
  31 + * 排班计划(使用Drools)。
  32 + */
  33 +public class DroolsSchedulePlan {
  34 + /** 主线路 */
  35 + private Line mainLine;
  36 + /** 套跑辅线路规则 */
  37 + private List<RerunRule_input> rerunRule_inputs;
  38 +
  39 + /** 开始排班时间 */
  40 + private Date from;
  41 + /** 结束排班时间 */
  42 + private Date to;
  43 + /** 排班计划entity */
  44 + private SchedulePlan schedulePlan;
  45 +
  46 + //-------------------- 相关的Repo,service服务 --------------------//
  47 + /** 线路Repo */
  48 + private LineRepository lineRepository;
  49 + /** 排班规则Repo */
  50 + private ScheduleRule1FlatRepository scheduleRule1FlatRepository;
  51 + /** 时刻表Repo */
  52 + private TTInfoRepository ttInfoRepository;
  53 + /** 时刻表明细Repo */
  54 + private TTInfoDetailRepository ttInfoDetailRepository;
  55 + /** 车辆配置Repo */
  56 + private CarConfigInfoRepository carConfigInfoRepository;
  57 + /** 人员配置Repo */
  58 + private EmployeeConfigInfoRepository employeeConfigInfoRepository;
  59 + /** 套跑规则Repo */
  60 + private RerunRuleRepository rerunRuleRepository;
  61 + /** 营运状态Repo */
  62 + private BusinessRepository businessRepository;
  63 +
  64 + /** 排班规则service */
  65 + private ScheduleRuleService scheduleRuleService;
  66 +
  67 + //-------------------- Drools KBase实例 ------------------//
  68 + /** 排班预处理KBase */
  69 + private KieBase preKBase;
  70 + /** 排班核心KBase */
  71 + private KieBase coreKBase;
  72 +
  73 + //-------------------- 日志记录器 ---------------------//
  74 + private Logger logger;
  75 +
  76 + public DroolsSchedulePlan(
  77 + SchedulePlan schedulePlan,
  78 + LineRepository lineRepository, ScheduleRule1FlatRepository scheduleRule1FlatRepository,
  79 + TTInfoRepository ttInfoRepository, TTInfoDetailRepository ttInfoDetailRepository,
  80 + CarConfigInfoRepository carConfigInfoRepository,
  81 + EmployeeConfigInfoRepository employeeConfigInfoRepository,
  82 + RerunRuleRepository rerunRuleRepository,
  83 + BusinessRepository businessRepository,
  84 + ScheduleRuleService scheduleRuleService,
  85 + KieBase preKBase, KieBase coreKBase,
  86 + Logger logger) {
  87 +
  88 + // 验证SchedulePlan实体
  89 + if (schedulePlan == null) {
  90 + throw new RuntimeException("排班用SchedulePlan为空!");
  91 + }
  92 + if (schedulePlan.getXl() == null) {
  93 + throw new RuntimeException("排班线路为空!");
  94 + } else {
  95 + // 获取主线路
  96 + this.mainLine = lineRepository.findOne(schedulePlan.getXl().getId());
  97 + if (this.mainLine == null) {
  98 + throw new RuntimeException("线路id=" + schedulePlan.getXl().getId() + "不存在!");
  99 + }
  100 + // 获取主线路套跑信息
  101 + this.rerunRule_inputs = scheduleRuleService.findRerunrule(this.mainLine.getId());
  102 + }
  103 + if (schedulePlan.getScheduleFromTime() == null) {
  104 + throw new RuntimeException("排班开始时间为空!");
  105 + }
  106 + if (schedulePlan.getScheduleToTime() == null) {
  107 + throw new RuntimeException("排班结束时间为空!");
  108 + }
  109 + this.from = schedulePlan.getScheduleFromTime();
  110 + this.to = schedulePlan.getScheduleToTime();
  111 + if (schedulePlan.getTtInfoIds() == null) {
  112 + throw new RuntimeException("排班关联的时刻表ids为空!");
  113 + }
  114 + if (schedulePlan.getTtInfoNames() == null) {
  115 + throw new RuntimeException("排班关联的时刻表名字s为空!");
  116 + }
  117 + this.schedulePlan = schedulePlan;
  118 +
  119 + this.lineRepository = lineRepository;
  120 + this.scheduleRule1FlatRepository = scheduleRule1FlatRepository;
  121 + this.ttInfoRepository = ttInfoRepository;
  122 + this.ttInfoDetailRepository = ttInfoDetailRepository;
  123 + this.carConfigInfoRepository = carConfigInfoRepository;
  124 + this.employeeConfigInfoRepository = employeeConfigInfoRepository;
  125 + this.rerunRuleRepository = rerunRuleRepository;
  126 + this.businessRepository = businessRepository;
  127 + this.scheduleRuleService = scheduleRuleService;
  128 + this.preKBase = preKBase;
  129 + this.coreKBase = coreKBase;
  130 +
  131 + this.logger = logger;
  132 +
  133 + }
  134 +
  135 + public void generatePlan() {
  136 + logger.info("<--- 排班master线路 id={}, name={}, 开始排班",
  137 + this.mainLine.getId(), this.mainLine.getName());
  138 +
  139 + // 1、确定主线路排班(包含完全套跑路牌规则,所谓完全套跑路牌规则指整个路牌的班次都是套跑规则指定的)
  140 + PlanResult planResult = this.schedulePlanWithOutRerun();
  141 +
  142 + // 2、确定套跑规则
  143 + this.rerunPlanResult(planResult);
  144 +
  145 + // TODO:3-1、验证排班结果
  146 + this.validPlanResult(planResult);
  147 +
  148 + // TODO:3-2、去除完全套跑遗漏班次(以后放到规则中执行)
  149 + Iterator<SchedulePlanInfo> infoIterator = planResult.getSchedulePlanInfos().iterator();
  150 + while (infoIterator.hasNext()) {
  151 + SchedulePlanInfo schedulePlanInfo = infoIterator.next();
  152 + if (schedulePlanInfo.getCl() == null) {
  153 + infoIterator.remove();
  154 + }
  155 + }
  156 +
  157 + // 4、保存数据(jdbcTemplate 批量插入)
  158 + Date start4 = new Date();
  159 + this.scheduleRuleService.generateSchedulePlan(
  160 + this.schedulePlan, planResult.getSchedulePlanInfos());
  161 + Date end4 = new Date();
  162 +
  163 + this.logger.info("保存主线路数据 {} 条 耗时 {} ms --->",
  164 + planResult.getSchedulePlanInfos().size(),
  165 + end4.getTime() - start4.getTime());
  166 + }
  167 +
  168 + /**
  169 + * 计算规则输入。
  170 + * @return
  171 + */
  172 + private List<ScheduleRule_input> calcuSrfList(Line line) {
  173 + // 1-1、构造drools规则输入数据,输出数据
  174 + // 全局计算参数
  175 + SchedulePlan schedulePlan = new SchedulePlan();
  176 + schedulePlan.setXl(line);
  177 + schedulePlan.setScheduleFromTime(this.from);
  178 + schedulePlan.setScheduleToTime(this.to);
  179 + ScheduleCalcuParam_input scheduleCalcuParam_input = new ScheduleCalcuParam_input(schedulePlan);
  180 +
  181 + // 规则输出数据
  182 + List<ScheduleRule_input> scheduleRule_inputs = new ArrayList<>();
  183 +
  184 + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
  185 + // 创建session,内部配置的是stateful
  186 + KieSession session = preKBase.newKieSession();
  187 + // 设置gloable对象,在drl中通过别名使用
  188 + session.setGlobal("sriList", scheduleRule_inputs);
  189 + session.setGlobal("log", logger); // 设置日志
  190 +
  191 + session.setGlobal("srf", scheduleRule1FlatRepository);
  192 + session.setGlobal("rrr", rerunRuleRepository);
  193 + session.setGlobal("srservice", scheduleRuleService);
  194 +
  195 + // 载入数据
  196 + session.insert(scheduleCalcuParam_input);
  197 +
  198 + // 执行rule
  199 + session.fireAllRules();
  200 +
  201 + // 执行完毕销毁,有日志的也要关闭
  202 + session.dispose();
  203 +
  204 + return scheduleRule_inputs;
  205 + }
  206 +
  207 + /**
  208 + * 时刻表选择(判定每天使用的时刻表,以及路牌数据输出)。
  209 + * @return [TTInfoResults_output, LpInfoResults_output]
  210 + */
  211 + private Object[] ttInfoOutput(Line line) {
  212 + // 获取线路的所有未作废的时刻表
  213 + List<TTInfo> ttInfos = ttInfoRepository.findInCanceledByXl(line);
  214 +
  215 + // 1-1、构造drools规则输入数据,输出数据
  216 + // 全局计算参数
  217 + TTInfoCalcuParam_input ttInfoCalcuParam_input =
  218 + new TTInfoCalcuParam_input(
  219 + new DateTime(this.from),
  220 + new DateTime(this.to),
  221 + String.valueOf(line.getId())
  222 + );
  223 + // 规则输出数据
  224 + TTInfoResults_output ttInfoResults_output = new TTInfoResults_output();
  225 + LpInfoResults_output lpInfoResults_output = new LpInfoResults_output();
  226 +
  227 + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
  228 + // 创建session,内部配置的是stateful
  229 + KieSession session = coreKBase.newKieSession();
  230 +
  231 + // 设置gloable对象,在drl中通过别名使用
  232 + session.setGlobal("results", ttInfoResults_output);
  233 + session.setGlobal("lpInfoResults_output", lpInfoResults_output);
  234 + session.setGlobal("log", logger); // 设置日志
  235 + session.setGlobal("tTInfoDetailRepository", ttInfoDetailRepository);
  236 +
  237 + // 载入数据
  238 + session.insert(ttInfoCalcuParam_input);
  239 + for (TTInfo ttInfo : ttInfos) {
  240 + TTInfo_input ttInfo_input = new TTInfo_input(ttInfo);
  241 + session.insert(ttInfo_input);
  242 + }
  243 +
  244 + // 载入数据2(计算规则最早启用时间)
  245 + List<ScheduleRule1Flat> scheduleRule1Flats = scheduleRule1FlatRepository.findByXl(line);
  246 +
  247 + for (ScheduleRule1Flat scheduleRule1Flat: scheduleRule1Flats) {
  248 + ScheduleRule_input scheduleRule_input = new ScheduleRule_input(scheduleRule1Flat);
  249 + session.insert(scheduleRule_input);
  250 + }
  251 +
  252 + // 执行rule
  253 + session.fireAllRules();
  254 +
  255 + // 执行完毕销毁,有日志的也要关闭
  256 + session.dispose();
  257 +
  258 + return new Object[] {ttInfoResults_output, lpInfoResults_output};
  259 +
  260 + }
  261 +
  262 + /**
  263 + * 循环规则输出。
  264 + * @param lpInfoResults_output 时刻表每日路牌的情况
  265 + */
  266 + private ScheduleResults_output loopRuleOutput(Line line, LpInfoResults_output lpInfoResults_output) {
  267 + // 1-1、构造drools规则输入数据,输出数据
  268 + // 全局计算参数
  269 + SchedulePlan schedulePlan = new SchedulePlan();
  270 + schedulePlan.setXl(line);
  271 + schedulePlan.setScheduleFromTime(this.from);
  272 + schedulePlan.setScheduleToTime(this.to);
  273 + schedulePlan.setIsHistoryPlanFirst(this.schedulePlan.getIsHistoryPlanFirst());
  274 + schedulePlan.setCreateBy(this.schedulePlan.getCreateBy());
  275 + ScheduleCalcuParam_input scheduleCalcuParam_input = new ScheduleCalcuParam_input(schedulePlan);
  276 + // 每个规则对应的输入参数
  277 + List<ScheduleRule_input> scheduleRule_inputs = this.calcuSrfList(line);
  278 +
  279 + // 规则输出数据
  280 + ScheduleResults_output scheduleResults_output = new ScheduleResults_output();
  281 +
  282 + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
  283 + // 创建session,内部配置的是stateful
  284 + KieSession session = coreKBase.newKieSession();
  285 + // 设置gloable对象,在drl中通过别名使用
  286 + session.setGlobal("scheduleResult", scheduleResults_output);
  287 + session.setGlobal("log", logger); // 设置日志
  288 + session.setGlobal("scheduleRuleService", scheduleRuleService);
  289 +
  290 + // 载入数据
  291 + session.insert(scheduleCalcuParam_input);
  292 + for (ScheduleRule_input scheduleRule_input : scheduleRule_inputs) {
  293 + session.insert(scheduleRule_input);
  294 + }
  295 + // 每日时刻表路牌数据
  296 + for (LpInfoResult_output lpInfoResult_output: lpInfoResults_output.getLpInfoResult_outputs()) {
  297 + session.insert(lpInfoResult_output);
  298 + }
  299 + // 执行rule
  300 + session.fireAllRules();
  301 +
  302 + // 执行完毕销毁,有日志的也要关闭
  303 + session.dispose();
  304 +
  305 + // 保存循环规则结果数据
  306 + scheduleRuleService.generateRuleResult(scheduleResults_output.getSchedulePlanRuleResults());
  307 +
  308 +// logger.info("循环规则输出={}", scheduleResults_output.showGuideboardDesc1());
  309 +
  310 + return scheduleResults_output;
  311 + }
  312 +
  313 + /**
  314 + * 排班生成。
  315 + * @param scheduleResults_output loopRuleOutput方法规则输出
  316 + * @param ttInfoResults_output ttInfoOutput方法规则输出
  317 + * @return PlanResult
  318 + */
  319 + private PlanResult planResultOutput(
  320 + Line line,
  321 + ScheduleResults_output scheduleResults_output,
  322 + TTInfoResults_output ttInfoResults_output) {
  323 +
  324 + SchedulePlan schedulePlan = new SchedulePlan();
  325 + schedulePlan.setXl(line);
  326 + schedulePlan.setScheduleFromTime(this.from);
  327 + schedulePlan.setScheduleToTime(this.to);
  328 + schedulePlan.setCreateBy(this.schedulePlan.getCreateBy());
  329 + schedulePlan.setUpdateBy(this.schedulePlan.getUpdateBy());
  330 +
  331 + // 1-1、构造drools规则输入数据,输出数据
  332 + PlanCalcuParam_input planCalcuParam_input = new PlanCalcuParam_input(
  333 + schedulePlan,
  334 + scheduleResults_output,
  335 + ttInfoResults_output
  336 + );
  337 + // 规则输出数据
  338 + PlanResult planResult = new PlanResult();
  339 + planResult.setXlId(schedulePlan.getXl().getId().toString());
  340 +
  341 + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
  342 + // 创建session,内部配置的是stateful
  343 + KieSession session = this.coreKBase.newKieSession();
  344 +
  345 + // 设置gloable对象,在drl中通过别名使用
  346 + session.setGlobal("planResult", planResult);
  347 + session.setGlobal("log", this.logger); // 设置日志
  348 +
  349 + session.setGlobal("tTInfoDetailRepository", this.ttInfoDetailRepository);
  350 + session.setGlobal("carConfigInfoRepository", this.carConfigInfoRepository);
  351 + session.setGlobal("employeeConfigInfoRepository", this.employeeConfigInfoRepository);
  352 + session.setGlobal("lineRepository", this.lineRepository);
  353 + session.setGlobal("businessRepository", this.businessRepository);
  354 +
  355 + // 载入数据
  356 + session.insert(planCalcuParam_input);
  357 +
  358 + // 执行rule
  359 + session.fireAllRules();
  360 +
  361 + // 执行完毕销毁,有日志的也要关闭
  362 + session.dispose();
  363 +
  364 + return planResult;
  365 +
  366 + }
  367 +
  368 + /**
  369 + * 生成线路排班(不含套跑规则)。
  370 + * @param schedulePlan
  371 + * @return
  372 + */
  373 + private PlanResult schedulePlanWithOutRerun() {
  374 + // 1、时刻表数据及每日路牌数据计算
  375 + Date start1 = new Date();
  376 + Object[] ttInfoRets = this.ttInfoOutput(this.mainLine);
  377 + TTInfoResults_output ttInfoResults_output = (TTInfoResults_output) ttInfoRets[0];
  378 + LpInfoResults_output lpInfoResults_output = (LpInfoResults_output) ttInfoRets[1];
  379 + Date end1 = new Date();
  380 + // 2、循环规则计算输出
  381 + Date start2 = new Date();
  382 + ScheduleResults_output scheduleResults_output = this.loopRuleOutput(
  383 + this.mainLine, lpInfoResults_output);
  384 + Date end2 = new Date();
  385 +
  386 + logger.info("规则计算结果={}", scheduleResults_output.showGuideboardDesc1());
  387 +
  388 + // 3、计划输出
  389 + Date start3 = new Date();
  390 + PlanResult planResult = planResultOutput(
  391 + this.mainLine, scheduleResults_output, ttInfoResults_output);
  392 + Date end3 = new Date();
  393 +
  394 + logger.info("drool时刻表每日路牌计算 {} ms,drool循环规则计算 {} ms,drool计划数据 {} ms",
  395 + end1.getTime() - start1.getTime(),
  396 + end2.getTime() - start2.getTime(),
  397 + end3.getTime() - start3.getTime());
  398 +
  399 + // TODO:将lpInfoResults_output 也要返回
  400 +
  401 + return planResult;
  402 + }
  403 +
  404 + /**
  405 + * 套跑计划排班数据。
  406 + * @param planResult
  407 + */
  408 + private void rerunPlanResult(PlanResult planResult) {
  409 + logger.info("套跑数量 {} 组", this.rerunRule_inputs.size());
  410 +
  411 + if (this.rerunRule_inputs.size() > 0) {
  412 + // 找出是对应路牌类型的线路,计算循环规则输出
  413 + Set<String> dylpxlids = new HashSet<>();
  414 + for (RerunRule_input rerunRule_input: rerunRule_inputs) {
  415 + if ("dylp".equals(rerunRule_input.getType())) {
  416 + dylpxlids.add(rerunRule_input.getS_xl()); // 参与套跑的线路
  417 + }
  418 + }
  419 +
  420 + List<ScheduleResults_output> scheduleResults_outputs = new ArrayList<>();
  421 + Date start1 = new Date();
  422 + for (String xlid: dylpxlids) {
  423 + Line dylpline = new Line(); // 套跑的线路默认跟着主线路设定走
  424 + dylpline.setId(Integer.parseInt(xlid));
  425 + // 获取套跑线路的循环规则计算输出
  426 + Object[] ttInfoRets = this.ttInfoOutput(dylpline);
  427 + LpInfoResults_output lpInfoResults_output = (LpInfoResults_output) ttInfoRets[1];
  428 + ScheduleResults_output scheduleResults_output = this.loopRuleOutput(
  429 + dylpline, lpInfoResults_output);
  430 + scheduleResults_outputs.add(scheduleResults_output);
  431 + }
  432 +
  433 + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
  434 + // 创建session,内部配置的是stateful
  435 + KieSession session = this.coreKBase.newKieSession();
  436 +
  437 + // 设置gloable对象,在drl中通过别名使用
  438 + session.setGlobal("planResult", planResult);
  439 + session.setGlobal("log", this.logger); // 设置日志
  440 +
  441 + session.setGlobal("carConfigInfoRepository", this.carConfigInfoRepository);
  442 + session.setGlobal("employeeConfigInfoRepository", this.employeeConfigInfoRepository);
  443 +
  444 + // 载入数据
  445 + RerunRule_param rerunRule_param = new RerunRule_param();
  446 + rerunRule_param.setMxlid(planResult.getXlId());
  447 + rerunRule_param.setXlIds_dylp(dylpxlids);
  448 + session.insert(rerunRule_param);
  449 + for (RerunRule_input rri: this.rerunRule_inputs) {
  450 + session.insert(rri);
  451 + }
  452 + for (SchedulePlanInfo spi: planResult.getSchedulePlanInfos()) {
  453 + session.insert(spi);
  454 + }
  455 + for (ScheduleResults_output sro: scheduleResults_outputs) {
  456 + session.insert(sro);
  457 + }
  458 +
  459 + // 执行rule
  460 + session.fireAllRules();
  461 +
  462 + // 执行完毕销毁,有日志的也要关闭
  463 + session.dispose();
  464 +
  465 + Date end1 = new Date();
  466 + logger.info("套跑规则计算,耗时 {} ms", end1.getTime() - start1.getTime());
  467 +
  468 + }
  469 +
  470 + }
  471 +
  472 + /**
  473 + * 验证排班结果。
  474 + * @param planResult
  475 + * @param schedulePlan
  476 + */
  477 + public void validPlanResult(PlanResult planResult) {
  478 + // 1-1、构造drools规则输入数据,输出数据
  479 + ValidateParam validateParam = new ValidateParam(
  480 + new DateTime(this.from), new DateTime(this.to));
  481 + // 规则输出数据
  482 + ValidateResults_output result = new ValidateResults_output();
  483 +
  484 + // 1-2、构造drools session->载入数据->启动规则->计算->销毁session
  485 + // 创建session,内部配置的是stateful
  486 + KieSession session = this.coreKBase.newKieSession();
  487 +
  488 + // 设置gloable对象,在drl中通过别名使用
  489 + session.setGlobal("validResult", result);
  490 + session.setGlobal("log", this.logger); // 设置日志
  491 +
  492 + // 载入数据
  493 + session.insert(validateParam);
  494 + for (SchedulePlanInfo schedulePlanInfo: planResult.getSchedulePlanInfos()) {
  495 + session.insert(schedulePlanInfo);
  496 + }
  497 +
  498 + // 执行rule
  499 + session.fireAllRules();
  500 +
  501 + // 执行完毕销毁,有日志的也要关闭
  502 + session.dispose();
  503 +
  504 +// logger.info("错误总数={}", result.getInfos().size());
  505 +// for (ValidateResults_output.ValidInfo validInfo: result.getInfos()) {
  506 +// logger.info(validInfo.getDesc());
  507 +// }
  508 +
  509 + // 取10条错误
  510 + int size = result.getInfos().size() > 10 ? 10: result.getInfos().size();
  511 + List<String> desclist = new ArrayList<>();
  512 + for (int i = 0; i < size; i++) {
  513 + desclist.add(result.getInfos().get(i).getDesc());
  514 + }
  515 + if (desclist.size() > 0) {
  516 + this.schedulePlan.setPlanResult(StringUtils.join(desclist, "</br>"));
  517 + } else {
  518 + this.schedulePlan.setPlanResult("ok");
  519 + }
  520 +
  521 + // TODO:设定错误信息
  522 + }
  523 +
  524 +}
... ...
src/main/java/com/bsth/service/schedule/rules/MyDroolsConfiguration.java
... ... @@ -28,7 +28,7 @@ public class MyDroolsConfiguration {
28 28 * 返回一个kiebase知识库,直接冲文件系统读入drl规则文件,
29 29 * TODO:以后需要从数据库读入规则文件,并重新创建kbase知识库。
30 30 */
31   - @Bean(name = "kb1")
  31 + @Bean(name = "coreKBase")
32 32 public KieBase myKieBase() {
33 33 // Drools 6开始引入kie统一接口(jboss的jbpm工作流也使用kie接口了),整个定义方式和5差别很大
34 34 // 这里使用全api方式创建知识库对象,不使用xml的方式,提供最大的灵活性
... ... @@ -105,7 +105,7 @@ public class MyDroolsConfiguration {
105 105 * 返回一个kiebase知识库,直接冲文件系统读入drl规则文件,
106 106 * TODO:以后需要从数据库读入规则文件,并重新创建kbase知识库。
107 107 */
108   - @Bean(name = "kb2")
  108 + @Bean(name = "preKBase")
109 109 public KieBase myKieBase2() {
110 110 // Drools 6开始引入kie统一接口(jboss的jbpm工作流也使用kie接口了),整个定义方式和5差别很大
111 111 // 这里使用全api方式创建知识库对象,不使用xml的方式,提供最大的灵活性
... ...