亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中動態(tài)規(guī)則的實現(xiàn)方式示例詳解

 更新時間:2020年08月25日 10:17:47   作者:阿凡盧  
這篇文章主要介紹了Java中動態(tài)規(guī)則的實現(xiàn)方式,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下

背景

業(yè)務(wù)系統(tǒng)在應(yīng)用過程中,有時候要處理“經(jīng)常變化”的部分,這部分需求可能是“業(yè)務(wù)規(guī)則”,也可能是“不同的數(shù)據(jù)處理邏輯”,這部分動態(tài)規(guī)則的問題,往往需要可配置,并對性能和實時性有一定要求。

Java不是解決動態(tài)層問題的理想語言,在實踐中發(fā)現(xiàn)主要有以下幾種方式可以實現(xiàn):

  • 表達式語言(expression language)
  • 動態(tài)語言(dynamic/script language language),如Groovy
  • 規(guī)則引擎(rule engine)

表達式語言

Java Unified Expression Language,簡稱JUEL,是一種特殊用途的編程語言,主要在JavaWeb應(yīng)用程序用于將表達式嵌入到web頁面。Java規(guī)范制定者和Java Web領(lǐng)域技術(shù)專家小組制定了統(tǒng)一的表達式語言。JUEL最初包含在JSP2.1規(guī)范JSR-245中,后來成為Java EE 7的一部分,改在JSR-341中定義。

主要的開源實現(xiàn)有:OGNLMVEL,SpELJUEL,Java Expression Language (JEXL)JEval,Jakarta JXPath等。

這里主要介紹在實踐中使用較多的MVEL、OGNL和SpEL。

OGNL(Object Graph Navigation Library)

在Struts 2 的標(biāo)簽庫中都是使用OGNL表達式訪問ApplicationContext中的對象數(shù)據(jù),簡單示例:

Foo foo = new Foo();
foo.setName("test");
Map<String, Object> context = new HashMap<String, Object>();
context.put("foo",foo);
String expression = "foo.name == 'test'";
try {
 Boolean result = (Boolean) Ognl.getValue(expression,context);
 System.out.println(result);
} catch (OgnlException e) {
 e.printStackTrace();
}

MVEL

MVEL最初作為Mike Brock創(chuàng)建的 Valhalla項目的表達式計算器(expression evaluator),相比最初的OGNL、JEXL和JUEL等項目,而它具有遠超它們的性能、功能和易用性 - 特別是集成方面。它不會嘗試另一種JVM語言,而是著重解決嵌入式腳本的問題。

MVEL主要使用在Drools,是Drools規(guī)則引擎不可分割的一部分。

MVEL語法較為豐富,不僅包含了基本的屬性表達式,布爾表達式,變量復(fù)制和方法調(diào)用,還支持函數(shù)定義,詳情參見MVEL Language Guide。

MVEL在執(zhí)行語言時主要有解釋模式(Interpreted Mode)和編譯模式(Compiled Mode)兩種:

解釋模式(Interpreted Mode)是一個無狀態(tài)的,動態(tài)解釋執(zhí)行,不需要負載表達式就可以執(zhí)行相應(yīng)的腳本。編譯模式(Compiled Mode)需要在緩存中產(chǎn)生一個完全規(guī)范化表達式之后再執(zhí)行。

//解釋模式
Foo foo = new Foo();
foo.setName("test");
Map context = new HashMap();
String expression = "foo.name == 'test'";
VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);
context.put("foo",foo);
Boolean result = (Boolean) MVEL.eval(expression,functionFactory);
System.out.println(result);

//編譯模式
Foo foo = new Foo();foo.setName("test");
Map context = new HashMap();
String expression = "foo.name == 'test'";
VariableResolverFactory functionFactory = new MapVariableResolverFactory(context);context.put("foo",foo);
Serializable compileExpression = MVEL.compileExpression(expression);

SpEL

SpEl(Spring表達式語言)是一個支持查詢和操作運行時對象導(dǎo)航圖功能的強大的表達式語言。 它的語法類似于傳統(tǒng)EL,但提供額外的功能,最出色的就是函數(shù)調(diào)用和簡單字符串的模板函數(shù)。SpEL類似于Struts2x中使用的OGNL表達式語言,能在運行時構(gòu)建復(fù)雜表達式、存取對象圖屬性、對象方法調(diào)用等等,并且能與Spring功能完美整合,如能用來配置Bean定義。

SpEL主要提供基本表達式、類相關(guān)表達式及集合相關(guān)表達式等,詳細參見Spring 表達式語言 (SpEL)。

類似與OGNL,SpEL具有expression(表達式),Parser(解析器),EvaluationContext(上下文)等基本概念;類似與MVEL,SpEl也提供了解釋模式和編譯模式兩種運行模式。

//解釋器模式
Foo foo = new Foo();
foo.setName("test");
// Turn on:
// - auto null reference initialization
// - auto collection growing
SpelParserConfiguration config = new SpelParserConfiguration(true,true);
ExpressionParser parser = new SpelExpressionParser(config);
String expressionStr = "#foo.name == 'test'";
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("foo",foo);
Expression expression = parser.parseExpression(expressionStr);
Boolean result = expression.getValue(context,Boolean.class);

//編譯模式
config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE, RunSpel.class.getClassLoader());
parser = new SpelExpressionParser(config);
context = new StandardEvaluationContext();
context.setVariable("foo",foo);
expression = parser.parseExpression(expressionStr);
result = expression.getValue(context,Boolean.class);

規(guī)則引擎

一些規(guī)則引擎(rule engine):aviatoreasy-rules,droolsesper

aviator

AviatorScript是一門高性能、輕量級寄宿于 JVM 之上的腳本語言。

使用場景包括:

  • 規(guī)則判斷及規(guī)則引擎
  • 公式計算
  • 動態(tài)腳本控制
  • 集合數(shù)據(jù) ELT 等
public class Test {
 public static void main(String[] args) {
  String expression = "a+(b-c)>100";
  // 編譯表達式
  Expression compiledExp = AviatorEvaluator.compile(expression);

  Map<String, Object> env = new HashMap<>();
  env.put("a", 100.3);
  env.put("b", 45);
  env.put("c", -199.100);

  // 執(zhí)行表達式
  Boolean result = (Boolean) compiledExp.execute(env);
  System.out.println(result);
 }
}

easy-rules

Easy Rules is a Java rules engine。

使用POJO定義規(guī)則:

@Rule(name = "weather rule", description = "if it rains then take an umbrella")
public class WeatherRule {

 @Condition
 public boolean itRains(@Fact("rain") boolean rain) {
  return rain;
 }
 
 @Action
 public void takeAnUmbrella() {
  System.out.println("It rains, take an umbrella!");
 }
}

Rule weatherRule = new RuleBuilder()
  .name("weather rule")
  .description("if it rains then take an umbrella")
  .when(facts -> facts.get("rain").equals(true))
  .then(facts -> System.out.println("It rains, take an umbrella!"))
  .build();

支持使用表達式語言(MVEL/SpEL)來定義規(guī)則:

weather-rule.ymlexample:

name: "weather rule"
description: "if it rains then take an umbrella"
condition: "rain == true"
actions:
 - "System.out.println(\"It rains, take an umbrella!\");"
MVELRuleFactory ruleFactory = new MVELRuleFactory(new YamlRuleDefinitionReader());
Rule weatherRule = ruleFactory.createRule(new FileReader("weather-rule.yml"));

觸發(fā)規(guī)則:

public class Test {
 public static void main(String[] args) {
  // define facts
  Facts facts = new Facts();
  facts.put("rain", true);

  // define rules
  Rule weatherRule = ...
  Rules rules = new Rules();
  rules.register(weatherRule);

  // fire rules on known facts
  RulesEngine rulesEngine = new DefaultRulesEngine();
  rulesEngine.fire(rules, facts);
 }
}

drools

An open source rule engine,DMN engineand complex event processing (CEP) engine for Java and the JVM Platform.

定義規(guī)則:

import com.lrq.wechatDemo.domain.User // 導(dǎo)入類
dialect "mvel"
rule "age" // 規(guī)則名,唯一
 when
  $user : User(age<15 || age>60) //規(guī)則的條件部分
 then
  System.out.println("年齡不符合要求!");
end

參考例子:

public class TestUser {
 private static KieContainer container = null;
 private KieSession statefulKieSession = null;

 @Test
 public void test(){
  KieServices kieServices = KieServices.Factory.get();
  container = kieServices.getKieClasspathContainer();
  statefulKieSession = container.newKieSession("myAgeSession");
  User user = new User("duval yang",12);
  statefulKieSession.insert(user);
  statefulKieSession.fireAllRules();
  statefulKieSession.dispose();
 }
}

esper

Esper is a component for complex event processing (CEP), streaming SQL and event series analysis, available for Java as Esper, and for .NET as NEsper.

一個例子:

public class Test {
 public static void main(String[] args) throws InterruptedException {
  EPServiceProvider epService = EPServiceProviderManager.getDefaultProvider();
 
  EPAdministrator admin = epService.getEPAdministrator();
 
  String product = Apple.class.getName();
  String epl = "select avg(price) from " + product + ".win:length_batch(3)";
 
  EPStatement state = admin.createEPL(epl);
  state.addListener(new AppleListener());
 
  EPRuntime runtime = epService.getEPRuntime();
 
  Apple apple1 = new Apple();
  apple1.setId(1);
  apple1.setPrice(5);
  runtime.sendEvent(apple1);
 
  Apple apple2 = new Apple();
  apple2.setId(2);
  apple2.setPrice(2);
  runtime.sendEvent(apple2);
 
  Apple apple3 = new Apple();
  apple3.setId(3);
  apple3.setPrice(5);
  runtime.sendEvent(apple3);
 }
}

drools和esper都是比較重的規(guī)則引擎,詳見其官方文檔。

動態(tài)JVM語言

Groovy

Groovy除了Gradle上的廣泛應(yīng)用之外,另一個大范圍的使用應(yīng)該就是結(jié)合Java使用動態(tài)代碼了。Groovy的語法與Java非常相似,以至于多數(shù)的Java代碼也是正確的Groovy代碼。Groovy代碼動態(tài)的被編譯器轉(zhuǎn)換成Java字節(jié)碼。由于其運行在JVM上的特性,Groovy可以使用其他Java語言編寫的庫。

Groovy可以看作給Java靜態(tài)世界補充動態(tài)能力的語言,同時Groovy已經(jīng)實現(xiàn)了java不具備的語言特性:

  • 函數(shù)字面值;
  • 對集合的一等支持;
  • 對正則表達式的一等支持;
  • 對xml的一等支持;

Groovy作為基于JVM的語言,與表達式語言存在語言級的不同,因此在語法上比表達還是語言更靈活。Java在調(diào)用Groovy時,都需要將Groovy代碼編譯成Class文件。

Groovy 可以采用GroovyClassLoader、GroovyShell、GroovyScriptEngine和JSR223等方式與Java語言集成。

一個使用GroovyClassLoader動態(tài)對json對象進行filter的例子:

public class GroovyFilter implements Filter {
 private static String template = "" +
   "package com.alarm.eagle.filter;" +
   "import com.fasterxml.jackson.databind.node.ObjectNode;" +
   "def match(ObjectNode o){[exp]}";

 private static String method = "match";

 private String filterExp;

 private transient GroovyObject filterObj;

 public GroovyFilter(String filterExp) throws Exception {
  ClassLoader parent = Thread.currentThread().getContextClassLoader();
  GroovyClassLoader classLoader = new GroovyClassLoader(parent);
  Class clazz = classLoader.parseClass(template.replace("[exp]", filterExp));
  filterObj = (GroovyObject)clazz.newInstance();
 }

 public boolean filter(ObjectNode objectNode) {
  return (boolean)filterObj.invokeMethod(method, objectNode);
 }
}

Java每次調(diào)用Groovy代碼都會將Groovy編譯成Class文件,因此在調(diào)用過程中會出現(xiàn)JVM級別的問題。如使用GroovyShell的parse方法導(dǎo)致perm區(qū)爆滿的問題,使用GroovyClassLoader加載機制導(dǎo)致頻繁gc問題和CodeCache用滿,導(dǎo)致JIT禁用問題等,相關(guān)問題可以參考深入學(xué)習(xí)java中的Groovy 和 Scala 類。

參考:

Java各種規(guī)則引擎:https://www.jianshu.com/p/41ea7a43093c

Java中使用動態(tài)代碼:http://brucefengnju.github.io/post/dynamic-code-in-java/

量身定制規(guī)則引擎,適應(yīng)多變業(yè)務(wù)場景:https://my.oschina.net/yygh/blog/616808?p=1

總結(jié)

到此這篇關(guān)于Java中動態(tài)規(guī)則的實現(xiàn)方式的文章就介紹到這了,更多相關(guān)Java動態(tài)規(guī)則內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Idea+Jconsole實現(xiàn)線程監(jiān)控步驟

    基于Idea+Jconsole實現(xiàn)線程監(jiān)控步驟

    這篇文章主要介紹了基于Idea+Jconsole實現(xiàn)線程監(jiān)控功能,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • 解決springboot集成rocketmq關(guān)于tag的坑

    解決springboot集成rocketmq關(guān)于tag的坑

    這篇文章主要介紹了解決springboot集成rocketmq關(guān)于tag的坑,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • IntelliJ IDEA 無法正常使用SVN的問題和完美解決辦法

    IntelliJ IDEA 無法正常使用SVN的問題和完美解決辦法

    這篇文章主要介紹了IntelliJ IDEA 無法正常使用SVN的問題和解決辦法,本文給大家分享完美解決方案,通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • MyBatis學(xué)習(xí)教程(五)-實現(xiàn)關(guān)聯(lián)表查詢方法詳解

    MyBatis學(xué)習(xí)教程(五)-實現(xiàn)關(guān)聯(lián)表查詢方法詳解

    本文給大家介紹mybatis關(guān)聯(lián)查詢,包括一對一關(guān)聯(lián)查詢,一對多關(guān)聯(lián)查詢,代碼簡單易懂,感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • java實現(xiàn)字符串轉(zhuǎn)String數(shù)組的方法示例

    java實現(xiàn)字符串轉(zhuǎn)String數(shù)組的方法示例

    這篇文章主要介紹了java實現(xiàn)字符串轉(zhuǎn)String數(shù)組的方法,涉及java字符串的遍歷、分割、轉(zhuǎn)換等相關(guān)操作技巧,需要的朋友可以參考下
    2017-10-10
  • SpringBoot整合iText7導(dǎo)出PDF及性能優(yōu)化方式

    SpringBoot整合iText7導(dǎo)出PDF及性能優(yōu)化方式

    在SpringBoot項目中整合iText7庫以導(dǎo)出PDF文件,不僅能夠滿足報告生成需求,而且可以處理復(fù)雜的文檔布局與樣式,整合步驟包括添加Maven依賴、編寫PDF生成代碼,性能優(yōu)化方面,建議使用流式處理、緩存樣式與字體、優(yōu)化HTML/CSS結(jié)構(gòu)、采用異步處理
    2024-09-09
  • 寧可用Lombok也不把成員設(shè)置為public原理解析

    寧可用Lombok也不把成員設(shè)置為public原理解析

    這篇文章主要為大家介紹了寧可用Lombok也不把成員設(shè)置為public原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • 幾種常見mybatis分頁的實現(xiàn)方式

    幾種常見mybatis分頁的實現(xiàn)方式

    這篇文章主要介紹了幾種常見mybatis分頁的實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • SpringBoot實現(xiàn)自定義Starter的步驟詳解

    SpringBoot實現(xiàn)自定義Starter的步驟詳解

    在SpringBoot中,Starter是一種特殊的依賴,它可以幫助我們快速地集成一些常用的功能,例如數(shù)據(jù)庫連接、消息隊列、Web框架等。在本文中,我們將介紹如何使用Spring Boot實現(xiàn)自定義Starter,需要的朋友可以參考下
    2023-06-06
  • Java Base64解碼錯誤及解決方法

    Java Base64解碼錯誤及解決方法

    本篇文章給大家從一個Java Base64解碼錯誤著手給大家分析了錯誤的原因以及解決辦法,有興趣的可以參考學(xué)習(xí)下。
    2018-02-02

最新評論