Skip to content

Script Plugin

对应模块: io.gitee.lcgyl:lcgyl-script-plugin

动态脚本引擎集成,支持在 Java 应用中安全地运行 Groovy, Aviator 等动态脚本。

✨ 特性

  • 多引擎适配 - 统一抽象接口,支持 Groovy, Aviator, QLExpress
  • 高性能缓存 - 脚本编译结果自动缓存,避免重复编译
  • 沙箱安全 - 可限制脚本权限,防止恶意代码执行
  • 灵活绑定 - 支持将 Spring Bean 或 Java 对象绑定到脚本上下文

🚀 快速开始

依赖引入

1. 引入核心模块

gradle
implementation 'io.gitee.lcgyl:lcgyl-script-plugin:2.2.0'

2. 选择脚本引擎(按需引入)

gradle
// Groovy 引擎支持
implementation 'io.gitee.lcgyl:lcgyl-script-groovy-plugin:2.2.0'

// Aviator 引擎支持
implementation 'io.gitee.lcgyl:lcgyl-script-aviator-plugin:2.2.0'

配置

yaml
lcgyl:
  script:
    default-engine: groovy  # groovy, aviator
    cache:
      enabled: true
      max-size: 1000
    sandbox:
      enabled: true
      allowed-classes:
        - java.lang.*
        - java.util.*

基础使用

java
@Service
public class ScriptService {
    
    @Inject
    private ScriptEngine scriptEngine;
    
    // 执行简单表达式
    public Object evaluate(String expression, Map<String, Object> context) {
        return scriptEngine.execute(expression, context);
    }
    
    // 计算价格(Aviator 表达式)
    public BigDecimal calculatePrice(BigDecimal basePrice, int quantity, double discount) {
        String expression = "basePrice * quantity * (1 - discount)";
        
        Map<String, Object> context = Map.of(
            "basePrice", basePrice,
            "quantity", quantity,
            "discount", discount
        );
        
        return (BigDecimal) scriptEngine.execute(expression, context);
    }
}

Groovy 脚本

java
@Service
public class GroovyScriptService {
    
    @Inject
    @Named("groovy")
    private ScriptEngine groovyEngine;
    
    // 执行 Groovy 脚本
    public Object runGroovy(String script, Map<String, Object> bindings) {
        return groovyEngine.execute(script, bindings);
    }
    
    // 动态规则校验
    public boolean validateOrder(Order order) {
        String script = """
            // 校验订单金额
            if (order.totalAmount > 10000) {
                return order.userId != null && order.addressId != null
            }
            return true
            """;
        
        return (boolean) groovyEngine.execute(script, Map.of("order", order));
    }
    
    // 动态计算运费
    public BigDecimal calculateShipping(Order order) {
        String script = """
            def weight = order.items.sum { it.weight * it.quantity }
            def basePrice = 10
            
            if (weight <= 1) return basePrice
            if (weight <= 5) return basePrice + (weight - 1) * 3
            return basePrice + 12 + (weight - 5) * 2
            """;
        
        return (BigDecimal) groovyEngine.execute(script, Map.of("order", order));
    }
}

规则引擎场景

java
@Service
public class RuleEngineService {
    
    @Inject
    private ScriptEngine scriptEngine;
    
    @Inject
    private RuleRepository ruleRepository;
    
    // 从数据库加载规则并执行
    public Object executeRule(String ruleCode, Map<String, Object> facts) {
        Rule rule = ruleRepository.findByCode(ruleCode);
        return scriptEngine.execute(rule.getScript(), facts);
    }
    
    // 促销规则计算
    public PromotionResult applyPromotion(Order order, String promotionCode) {
        Promotion promotion = promotionRepository.findByCode(promotionCode);
        
        Map<String, Object> context = Map.of(
            "order", order,
            "user", userService.getUser(order.getUserId()),
            "helper", new PromotionHelper()  // 辅助工具类
        );
        
        return (PromotionResult) scriptEngine.execute(promotion.getScript(), context);
    }
}

沙箱安全

java
@Service
public class SafeScriptService {
    
    @Inject
    private ScriptEngineFactory engineFactory;
    
    public Object executeSandboxed(String script, Map<String, Object> context) {
        // 创建受限的脚本引擎
        ScriptEngine sandboxEngine = engineFactory.create(ScriptConfig.builder()
            .sandbox(true)
            .maxExecutionTime(Duration.ofSeconds(5))
            .maxMemory(10 * 1024 * 1024)  // 10MB
            .allowedClasses(List.of(
                "java.lang.String",
                "java.lang.Math",
                "java.util.List",
                "java.util.Map"
            ))
            .build());
        
        return sandboxEngine.execute(script, context);
    }
}

Released under the Apache License 2.0