Sprievodca jazykovým jazykom jari

1. Prehľad

Jazyk Spring Expression Language (SpEL) je výkonný výrazový jazyk, ktorý podporuje dopytovanie a manipuláciu s objektovým grafom za behu programu. Môže byť použitý s konfiguráciami Spring alebo XML založenými na anotáciách.

V jazyku je k dispozícii niekoľko operátorov:

TypOperátorov
Aritmetika+, -, *, /,%, ^, div, mod
Relačné, ==,! =, =, lt, gt, eq, ne, le, ge
Logickéa, alebo nie, &&, ||,!
Podmienené?:
Regulárny výrazzápasy

2. Prevádzkovatelia

Pre tieto príklady použijeme konfiguráciu založenú na anotáciách. Viac podrobností o konfigurácii XML nájdete v ďalších častiach tohto článku.

Výrazy SpEL začínajú znakom # symbol a sú zabalené do zátvoriek: # {expression}. Na nehnuteľnosti je možné odkazovať podobným spôsobom, počnúc a $ symbol a zabalené do zátvoriek: $ {property.name}. Zástupné symboly vlastností nemôžu obsahovať výrazy SpEL, ale výrazy môžu obsahovať odkazy na vlastnosti:

# {$ {someProperty} + 2}

Vo vyššie uvedenom príklade predpokladajme nejaká vlastnosť má hodnotu 2, takže výsledný výraz by bol 2 + 2, ktorý by sa vyhodnotil na 4.

2.1. Aritmetické operátory

Podporované sú všetky základné aritmetické operátory.

@Value ("# {19 + 1}") // 20 súkromných dvojitých pridaní; @Value ("# {'String1' + 'string2'}") // "String1 string2" private String addString; @Value ("# {20 - 1}") // 19 dvojité súkromné ​​odpočítanie; @Value ("# {10 * 2}") // 20 súkromných dvojnásobných znásobení; @Value ("# {36/2}") // 19 dvojité súkromné ​​rozdelenie; @Value ("# {36 div 2}") // 18, to isté ako pre / operator private double divideAlphabetic; @Value ("# {37% 10}") // 7 súkromných dvojitých modulov; @Value ("# {37 mod 10}") // 7, rovnaké ako pre operátora% operator private double moduloAlphabetic; @Value ("# {2 ^ 9}") // 512 private double powerOf; @Value ("# {(2 + 2) * 2 + 9}") // 17 súkromných dvojitých zátvoriek; 

Operácie rozdelenia a modulo majú abecedné aliasy, div pre / a mod pre %. The + operátor sa dá použiť aj na zreťazenie reťazcov.

2.2. Relačné a logické operátory

Podporované sú tiež všetky základné relačné a logické operácie.

@Value ("# {1 == 1}") // true private boolean equal; @Value ("# {1 eq 1}") // true private boolean equalAlphabetic; @Value ("# {1! = 1}") // false private boolean notEqual; @Value ("# {1 ne 1}") // false private boolean notEqualAlphabetic; @Value ("# {1 <1}") // false private boolean lessThan; @Value ("# {1 lt 1}") // false private boolean lessThanAlphabetic; @Value ("# {1 1}") // false private boolean greaterThan; @Value ("# {1 gt 1}") // false false boolean greaterThanAlphabetic; @Value ("# {1> = 1}") // true private boolean greaterThanOrEqual; @Value ("# {1 ge 1}") // true private boolean greaterThanOrEqualAlphabetic; 

Všetky relačné operátory majú tiež abecedné aliasy. Napríklad v konfiguráciách založených na XML nemôžeme použiť operátory obsahujúce lomené zátvorky (<, <=,>, >=). Namiesto toho môžeme použiť lt (menej ako), le (menšie alebo rovnaké), gt (väčšie ako) alebo ge (väčší alebo rovný).

2.3. Logickí operátori

SpEL podporuje všetky základné logické operácie:

@Value ("#") // true private boolean aleboAlphabetetic; @Value ("# {! True}") // false private boolean nie; @Value ("# {not true}") // false private boolean notAlphabetetic;

Rovnako ako u aritmetických a relačných operátorov, aj všetky logické operátory majú abecedné klony.

2.4. Podmienení operátori

Podmienené operátory sa používajú na vloženie rôznych hodnôt v závislosti od niektorých podmienok:

@Value ("# {2> 1? 'A': 'b'}") // "a" súkromný reťazec ternárny;

Ternárny operátor sa používa na vykonávanie kompaktnej podmienenej logiky typu if-then-else vo vnútri výrazu. V tomto príklade sa snažíme skontrolovať, či tam bol pravda alebo nie.

Ďalším bežným používaním ternárneho operátora je skontrolovať, či je nejaká premenná nulový a potom vráťte hodnotu premennej alebo predvolenú hodnotu:

@Value ("# {someBean.someProperty! = Null? SomeBean.someProperty: 'default'}") private String ternary;

Operátor Elvis je spôsob skrátenia syntaxe ternárneho operátora pre vyššie uvedený prípad používaný v jazyku Groovy. Je k dispozícii aj v SpEL. Nasledujúci kód je ekvivalentom vyššie uvedeného kódu:

@Value ("# {someBean.someProperty?: 'Default'}") // // Vloží zadaný reťazec, ak someProperty je null private String elvis;

2.5. Používanie Regexu v SpEL

The zápasy pomocou operátora je možné skontrolovať, či sa reťazec zhoduje s daným regulárnym výrazom alebo nie.

@Value ("# {'100' zodpovedá '\ d +'}") // true private boolean validNumericStringResult; @Value ("# {'100fghdjf' zodpovedá '\ d +'}") // false private boolean invalidNumericStringResult; @Value ("# {'platný abecedný reťazec' sa zhoduje s [[a-zA-Z \ s] + '}") "// true private boolean validAlphabeticStringResult; @Value ("# {'neplatný abecedný reťazec # $ 1' sa zhoduje s [[a-zA-Z \ s] + '}")) // false private boolean invalidAlphabeticStringResult; @Value ("# {someBean.someValue matches '\ d +'}") // true, ak someValue obsahuje iba číslice private boolean validNumericValue;

2.6. Prístup Zoznam a Mapa Predmety

S pomocou SpEL môžeme pristupovať k obsahu ľubovoľného Mapa alebo Zoznam v kontexte. Vytvoríme novú fazuľu workersHolder ktorá uloží informácie o niektorých pracovníkoch a ich platoch do a Zoznam a a Mapa:

@Component ("workersHolder") verejná trieda WorkersHolder {súkromný zoznam pracovníkov = nový LinkedList (); súkromná mapa platByWorkers = nový HashMap (); public WorkersHolder () {workers.add ("John"); workers.add ("Susie"); workers.add („Alex“); workers.add („George“); platByWorkers.put ("John", 35000); platByWorkers.put ("Susie", 47000); platByWorkers.put ("Alex", 12000); platByWorkers.put ("George", 14000); } // Getters and Setters}

Teraz môžeme pristupovať k hodnotám zbierok pomocou SpEL:

@Value ("# {workersHolder.salaryByWorkers ['John']}") // 35 000 súkromných celých čísel johnSalary; @Value ("# {workersHolder.salaryByWorkers ['George']}") // 14 000 súkromných celých čísel georgeSalary; @Value ("# {workersHolder.salaryByWorkers ['Susie']}" ") // 47 000 súkromných celých čísel susieSalary; @Value ("# {workersHolder.workers [0]}") // John private String firstWorker; @Value ("# {workersHolder.workers [3]}") // George private String lastWorker; @Value ("# {workersHolder.workers.size ()}") // 4 súkromné ​​celé čísloOfWorkers;

3. Použite v jarnej konfigurácii

3.1. Odkazy na fazuľa

V tomto príklade sa pozrieme na to, ako používať SpEL v konfigurácii založenej na XML. Výrazy môžu byť použité ako odkaz na fazuľa alebo fazuľové polia / metódy. Predpokladajme napríklad, že máme nasledujúce triedy:

public class Engine {private int kapacita; private int horsePower; private int numberOfCylinders; // Getters and setters} public class Car {private String make; súkromný int model; súkromný motor motora; private int horsePower; // Getters and setters}

Teraz vytvoríme kontext aplikácie, v ktorej sa výrazy používajú na vloženie hodnôt:

Pozrite sa na someCar fazuľa. The motor a Konská sila polia someCar používať výrazy, ktoré sú fazuľovými odkazmi na motor fazuľa a Konská sila pole resp.

To isté urobte s konfiguráciami založenými na anotáciách, použite @Value („# {expression}“) anotácia.

3.2. Používanie operátorov v konfigurácii

Každý operátor z prvej časti tohto článku možno použiť v konfiguráciách založených na XML a anotáciách. Pamätajte však, že v konfigurácii založenej na XML nemôžeme použiť operátor uhlovej zátvorky „<“. Namiesto toho by sme mali používať abecedné aliasy, ako napríklad lt (menej ako) alebo le (menšie alebo rovné). Pre konfigurácie založené na anotáciách neexistujú žiadne také obmedzenia.

public class SpelOperators {private boolean equal; private boolean notEqual; private boolean greaterThanOrEqual; súkromné ​​booleovské a; súkromné ​​booleovské alebo; private String addString; // Getters and Setters
 @Override public String toString () {// toString, ktorý obsahuje všetky polia}

Teraz pridáme a spelOperators fazuľa do kontextu aplikácie:

   = 6} "/> 300 alebo someCar.engine.capacity> 3000}" />

Po načítaní tejto fazule z kontextu potom môžeme overiť, či boli hodnoty vložené správne:

ApplicationContext context = nový ClassPathXmlApplicationContext ("applicationContext.xml"); SpelOperators spelOperators = (SpelOperators) context.getBean ("spelOperators"); 

Tu vidíme výstup súboru natiahnuť metóda spelOperators fazuľa:

[equal = true, notEqual = false, greaterThanOrEqual = true a = true, alebo = true, addString = Niektoré modely vyrábané niektorými výrobcami] 

4. Programová analýza výrazov

Niekedy môžeme chcieť analyzovať výrazy mimo kontextu konfigurácie. Našťastie je to možné pomocou SpelExpressionParser. Môžeme použiť všetky operátory, ktoré sme videli v predchádzajúcich príkladoch, ale mali by sme ich používať bez zložených zátvoriek a symbolu hash. Teda, ak chceme použiť výraz s + operátor, keď sa používa v jarnej konfigurácii, je syntax #{1 + 1}; ak sa použije mimo konfigurácie, syntax je jednoduchá 1 + 1.

V nasledujúcich príkladoch použijeme Auto a Motor fazuľa definovaná v predchádzajúcej časti.

4.1. Použitím ExpressionParser

Pozrime sa na jednoduchý príklad:

ExpressionParser expressionParser = nový SpelExpressionParser (); Výraz expression = expressionParser.parseExpression ("" Ľubovoľný reťazec ""); Výsledok reťazca = (Reťazec) expression.getValue (); 

ExpressionParser je zodpovedný za analýzu výrazových reťazcov. V tomto príklade syntaktický analyzátor SpEL jednoducho vyhodnotí reťazec „Ľubovoľný reťazec“ ako výraz. Výsledok nebude prekvapením „Ľubovoľný reťazec“.

Rovnako ako pri použití SpEL v konfigurácii, môžeme ho použiť na volanie metód, prístup k vlastnostiam alebo na vyvolanie konštruktérov.

Výraz expression = expressionParser.parseExpression ("" Ľubovoľný reťazec ". Dĺžka ()"); Výsledok celého čísla = (Celé číslo) expression.getValue ();

Okrem toho, že priamo nemusíme priamo pracovať s literálom, môžeme zavolať konštruktor:

Výraz expression = expressionParser.parseExpression ("new String ('Any string'). Length ()");

Môžeme tiež získať prístup k bajtov majetok String triedy rovnakým spôsobom, výsledkom čoho je reprezentácia reťazca v bajtoch []:

Výraz expression = expressionParser.parseExpression ("" Ľubovoľný reťazec ". Bajty"); byte [] result = (byte []) expression.getValue ();

Môžeme reťaziť volania metód, rovnako ako v bežnom kóde Java:

Výraz expression = expressionParser.parseExpression ("„ Ľubovoľný reťazec ". Nahradiť (\" \ ", \" \ "). Length ()"); Výsledok celého čísla = (Celé číslo) expression.getValue ();

V takom prípade bude výsledok 9, pretože sme medzery nahradili prázdnym reťazcom. Ak nechceme prenášať výsledok výrazu, môžeme použiť všeobecnú metódu T getValue (požadovaná triedaResultType), v ktorom môžeme poskytnúť požadovaný typ triedy, ktorý chceme vrátiť. Poznač si to EvaluationException bude vyhodené, ak vrátenú hodnotu nie je možné odovzdať do požadovanýResultType:

Výsledok celého čísla = expression.getValue (Integer.class);

Najbežnejšie použitie je poskytnúť reťazec výrazu, ktorý sa vyhodnotí proti konkrétnej inštancii objektu:

Automobil = nové auto (); car.setMake („Dobrý výrobca“); car.setModel ("Model 3"); car.setYearOfProduction (2014); ExpressionParser expressionParser = nový SpelExpressionParser (); Výraz expression = expressionParser.parseExpression ("model"); EvaluationContext context = nový StandardEvaluationContext (auto); Výsledok reťazca = (Reťazec) expression.getValue (kontext);

V takom prípade sa výsledok bude rovnať hodnote Model pole auto objekt, “Model 3„. The StandardEvaluationContext trieda určuje, proti ktorému objektu bude výraz vyhodnotený.

Po vytvorení kontextového objektu to nie je možné zmeniť. StandardEvaluationContext je nákladné zostaviť a počas opakovaného použitia vytvára stav v medzipamäti, ktorý umožňuje rýchlejšie vykonávanie následných hodnotení výrazov. Osvedčeným postupom je opätovné použitie z dôvodu ukladania do pamäte cache StandardEvaluationContext kde je to možné, ak sa koreňový objekt nezmení.

Ak sa však objekt root opakovane mení, môžeme použiť mechanizmus zobrazený v príklade nižšie:

Výraz expression = expressionParser.parseExpression ("model"); Výsledok reťazca = (Reťazec) expression.getValue (auto);

Tu hovoríme getValue metóda s argumentom, ktorý predstavuje objekt, na ktorý chceme aplikovať výraz SpEL. Môžeme tiež použiť všeobecné getValue rovnako ako predtým:

Výraz výraz = expressionParser.parseExpression ("yearOfProduction> 2005"); boolean result = expression.getValue (auto, Boolean.class);

4.2. Použitím ExpressionParser na nastavenie hodnoty

Pomocou setValue metóda na Vyjadrenie objekt vrátený analýzou výrazu, môžeme na objektoch nastaviť hodnoty. O konverziu typu sa postará SpEL. Predvolene používa SpEL org.springframework.core.convert.ConversionService. Medzi typmi si môžeme vytvoriť vlastný prevodník. ConversionService vie generikum, takže sa dá použiť s generikami. Pozrime sa, ako to môžeme v praxi využiť:

Automobil = nové auto (); car.setMake („Dobrý výrobca“); car.setModel ("Model 3"); car.setYearOfProduction (2014); CarPark carPark = nový CarPark (); carPark.getCars (). add (auto); StandardEvaluationContext context = nový StandardEvaluationContext (carPark); ExpressionParser expressionParser = nový SpelExpressionParser (); expressionParser.parseExpression ("cars [0] .model"). setValue (kontext, "Iný model");

Výsledný objekt automobilu bude mať ModelIný model”Ktorý bol zmenený z“Model 3“.

4.3. Konfigurácia analyzátora

V nasledujúcom príklade použijeme nasledujúcu triedu:

verejná trieda CarPark {súkromné ​​zoznamy automobilov = nový ArrayList (); // Zakladač a nastavovač}

Je možné nakonfigurovať ExpressionParser zavolaním konštruktora pomocou a SpelParserConfiguration objekt. Napríklad, ak sa pokúsime pridať auto predmet do autá pole Parkovisko triedy bez konfigurácie syntaktického analyzátora, zobrazí sa chyba ako táto:

EL1025E: (poz. 4): Zbierka obsahuje prvky „0“, index „0“ je neplatný

Môžeme zmeniť správanie analyzátora, aby sme mu umožnili automatické vytváranie prvkov, ak je zadaný index nulový (autoGrowNullReferences, prvý parameter konštruktoru) alebo na automatické zväčšenie poľa alebo zoznamu, aby sa do nich zmestili prvky presahujúce jeho pôvodnú veľkosť (autoGrowCollections, druhý parameter).

SpelParserConfiguration config = nový SpelParserConfiguration (true, true); StandardEvaluationContext context = nový StandardEvaluationContext (carPark); ExpressionParser expressionParser = nový SpelExpressionParser (konfigurácia); expressionParser.parseExpression ("autá [0]"). setValue (kontext, auto); Výsledok auta = carPark.getCars (). Get (0);

Výsledný auto objekt sa bude rovnať auto objekt, ktorý bol nastavený ako prvý prvok autá pole parkovisko objekt z predchádzajúceho príkladu.

5. Záver

SpEL je výkonný a dobre podporovaný výrazový jazyk, ktorý je možné použiť vo všetkých produktoch z portfólia Spring. Môže sa použiť na konfiguráciu aplikácií Spring alebo na zápis analyzátorov na vykonávanie všeobecnejších úloh v ľubovoľnej aplikácii.

Ukážky kódu v tomto článku sú k dispozícii v prepojenom úložisku GitHub.


$config[zx-auto] not found$config[zx-overlay] not found