您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關基于Spring EL如何實現一個簡單的電商打折優惠規則引擎,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
基于Spring EL實現一個簡單的電商打折優惠規則引擎
在日常工作中,能遇到使用規則引擎的地方非常的多。比如,電商中的打折優惠場景,復雜多變。再比如,考勤分析時每個部門都有不同的分析策略。還有薪資計算,公司中不同職級,不同辦公地點的算薪方式都不同。這些場景都非常的適合使用規則引擎。
說到規則引擎,大部分人可能首先想到的是 Drools,但其實 Spring EL 也很好用。
WTF?Spring EL還能做規則引擎?
你沒有看錯,Spring EL不僅能做規則引擎,我還在生產環境大范圍的使用了。
相對于別的規則引擎,Spring EL 更加輕量級,學習成本更低,與函數式編程配合表現可能超乎你的想象!
當一個系統的某項業務規則多變時,需要設計的非常的靈活,如果用傳統硬編碼的方式去做,可能導致代碼邏輯異常復雜,而且需要改動得非常頻繁。
為了解決這個問題,我打算引入腳本引擎去簡化開發,降低系統復雜度,在考察過后,最終決定用 Spring EL。
首先,我們先來定義一個結算的基礎對象。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
private String userId;
private Integer age;
//是否是新客
private Boolean isNew;
private LocalDate orderDate;
private BigDecimal price;
}
如果有一個供應商有一條結算規則是分成訂單金額的80%,我們可以這樣計算。
public static void main(String[] args){
ExpressionParser expressionParser = new SpelExpressionParser();
Expression expression = expressionParser.parseExpression("price * 0.8");
Order order = new Order();
order.setPrice(BigDecimal.TEN);
BigDecimal value = expression.getValue(order, BigDecimal.class);
System.out.println(value);
}
這樣就能算出應該結算 8元,當然這個例子太簡單了,我們定義幾個復雜的結算規則,看看應該如何去做。
規則1:周一周五新客結算,結算金額為 price * 0.2
規則2: 年齡大于18歲、金額大于10的結算,結算金額為(price - 10) * 0.8 我們來看上面的規則,實際上是分成了兩步,第一步是過濾掉不結算的訂單,第二步是真正的計算金額,因此代碼我們也可以分這兩步走
我先定義幾個測試用例
List<Order> orders = new ArrayList<Order>(){{
//年齡19,不是新客,周一下單,金額11
add(new Order("張三",19,false,LocalDate.of(2020,11,9),new BigDecimal(11)));
//年齡17,是新客,周五下單,金額19
add(new Order("李四",17,true,LocalDate.of(2020,11,13),new BigDecimal(19)));
//年齡17,不是新客,周六下單,金額9
add(new Order("王五",17,true,LocalDate.of(2020,11,14),new BigDecimal(9)));
}};
主要邏輯如下,先過濾掉不需要的訂單,然后對剩下的訂單進行結算。
public static void settle(List<Order> orders, List<String> filterRule,
String settleRule, Map<String, Expression> expressionCache) {
Stream<Order> stream = orders.stream();
for (String rule : filterRule) {
Expression expression = FunctionUtil
.cacheFunction(s -> expressionParser.parseExpression(s), rule, expressionCache);
stream = filter(stream, expression);
}
Expression expression = FunctionUtil
.cacheFunction(s -> expressionParser.parseExpression(s), settleRule, expressionCache);
stream.forEach(o -> System.out.println(o.getUserId() + expression.getValue(o)));
}
public static <T> Stream<T> filter(Stream<T> stream, Expression expression) {
return stream.filter(s -> expression.getValue(s, Boolean.class));
}
FunctionUtil.cacheFunction() 的作用是對 Expression 進行緩存,因為創建 Expression 的代價比較高,因此把 String 規則作為 key,Expression 作為 value 緩存一下。
執行一下代碼。
public static void main(String[] args) {
Map<String, Expression> expressionCache = new HashMap<String, Expression>();
System.out.println("結算rule1");
List<String> filterRule1 =
Arrays.asList("orderDate.getDayOfWeek().getValue() == 1 || orderDate.getDayOfWeek().getValue() == 5", "isNew");
String settleRule1 = "price * 0.2";
settle(orders, filterRule1, settleRule1, expressionCache);
System.out.println("結算rule2");
List<String> filterRule2 = Arrays.asList("age > 18", "price > 10");
String settleRule2 = "(price - 10) * 0.8";
settle(orders, filterRule2, settleRule2, expressionCache);
}
執行結果。
結算rule1
李四3.8
結算rule2
張三0.8
可以看到,通過 Spring EL 和函數式編程,我們只需要編寫規則就可以實現復雜的結算邏輯。
看完上述內容,你們對基于Spring EL如何實現一個簡單的電商打折優惠規則引擎有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。