Tavaszi kifejezés nyelv útmutató

1. Áttekintés

A Spring Expression Language (SpEL) egy erőteljes kifejezésnyelv, amely támogatja az objektumgrafikon futás közbeni lekérdezését és kezelését. XML vagy annotáció alapú Spring konfigurációkkal használható.

Számos operátor érhető el a nyelven:

típusOperátorok
Számtan+, -, *, /,%, ^, div, mod
Relációs, ==,! =, =, lt, gt, eq, ne, le, ge
Logikusés, vagy nem, &&, ||,!
Feltételes?:
Regexmérkőzések

2. Operátorok

Ezekhez a példákhoz annotáció alapú konfigurációt fogunk használni. Az XML-konfigurációról további részletek a cikk későbbi szakaszaiban találhatók.

A SpEL kifejezések a # szimbólumot, és zárójelbe vannak csomagolva: #{kifejezés}. A tulajdonságokra hasonló módon hivatkozhatunk, kezdve az a-val $ szimbólumot és zárójelbe csomagolva: $ {property.name}. A tulajdonságok helyőrzői nem tartalmazhatnak SpEL kifejezéseket, de a kifejezések tartalmazhatnak tulajdonság hivatkozásokat:

# {$ {someProperty} + 2}

A fenti példában feltételezzük someProperty értéke 2, így a kapott kifejezés 2 + 2 lenne, amelyet 4-re értékelnénk.

2.1. Számtani operátorok

Az összes számtani operátor támogatott.

@Value ("# {19 + 1}") // 20 privát dupla hozzáadás; @Value ("# {'String1' + 'string2'}") // "String1 string2" privát karakterlánc addString; @Value ("# {20 - 1}") // 19 privát kettős kivonás; @Value ("# {10 * 2}") // 20 privát kettős szorzás; @Value ("# {36/2}") // 19 privát kettős megosztottság; @Value ("# {36 div 2}") // 18, ugyanaz, mint a / operator private double divideAlphabetic esetében; @Value ("# {37% 10}") // 7 privát kettős modulo; @Value ("# {37 mod 10}") // 7, ugyanaz, mint a% operátor privát kettős moduloAlphabetic esetében; @Value ("# {2 ^ 9}") // 512 privát kettős powerOf; @Value ("# {(2 + 2) * 2 + 9}") // 17 privát dupla zárójel; 

A divide és modulo műveleteknek vannak alfabetikus álnevei, div mert / és mod mert %. A + operátor a húrok összefűzésére is használható.

2.2. Relációs és logikai operátorok

Minden alapvető relációs és logikai művelet is támogatott.

@Value ("# {1 == 1}") // valódi privát logikai egyenlő; @Value ("# {1 eq 1}") // valódi privát logikai egyenlőAlphabetic; @Value ("# {1! = 1}") // hamis privát logikai notEqual; @Value ("# {1 ne 1}") // hamis privát logikai notEqualAlphabetic; @Value ("# {1 <1}") // hamis privát logikai érték kevesebbThan; @Value ("# {1 lt 1}") // hamis privát logikai érték kevesebbThanAlphabetic; @Value ("# {1 1}") // hamis privát logikai érték nagyobbThan; @Value ("# {1 gt 1}") // hamis privát logikai érték nagyobbThanAlphabetic; @Value ("# {1> = 1}") // igazi privát logikai érték nagyobbThanOrEqual; @Value ("# {1 ge 1}") // igazi privát logikai érték nagyobbThanOrEqualAlphabetic; 

Minden relációs operátornak vannak ábécés álnevei is. Például XML-alapú konfigurációkban nem használhatunk szögletes zárójelet (<, <=,>, >=). Ehelyett használhatjuk lt (kevesebb, mint), le (kisebb vagy egyenlő), gt (nagyobb, mint), vagy ge (nagyobb vagy egyenlő).

2.3. Logikai operátorok

A SpEL támogatja az összes alapvető logikai műveletet:

@Value ("#") // igazi privát logikai vagy ábécés; @Value ("# {! True}") // hamis privát logikai érték nem; @Value ("# {not true}") // hamis privát logikai notAlphabetic;

Csakúgy, mint az aritmetikai és relációs operátorok esetében, minden logikai operátornak van ábécés klónja is.

2.4. Feltételes operátorok

A feltételes operátorokat különböző feltételek injektálására használják bizonyos feltételektől függően:

@Value ("# {2> 1? 'A': 'b'}") // "a" privát String ternary;

A háromszintű operátor kompakt, ha-akkor-más feltételes logika végrehajtására szolgál a kifejezésen belül. Ebben a példában megpróbáljuk ellenőrizni, hogy volt-e ilyen igaz vagy nem.

A ternáris operátor másik gyakori használata annak ellenőrzése, hogy van-e valamilyen változó nulla majd adja vissza a változó értékét vagy egy alapértelmezett értékét:

@Value ("# {someBean.someProperty! = Null? SomeBean.someProperty: 'default'}") privát karakterlánc hármas;

Az Elvis operátor a fenti esetben a Groovy nyelvben használt terner operátor szintaxisának rövidítésére szolgál. SpEL-ben is elérhető. Az alábbi kód megegyezik a fenti kóddal:

@Value ("# {someBean.someProperty?: 'Default'}") // A megadott karakterláncot injektálja, ha a someProperty értéke null privát String elvis;

2.5. A Regex használata a SpEL-ben

A mérkőzések operátor segítségével ellenőrizhető, hogy egy karakterlánc megfelel-e egy adott reguláris kifejezésnek.

@Value ("# {'100' egyezik '\ d +'}") // true private logikai érték validNumericStringResult; @Value ("# {'100fghdjf' egyezik '\ d +'}") // hamis privát logikai érték érvénytelenNumericStringResult; @Value ("# {'érvényes alfabetikus karakterlánc' egyezik '[a-zA-Z \ s] +'}") // true private boolean validAlphabeticStringResult; @Value ("# {'érvénytelen ABC # # 1" megfelel "[a-zA-Z \ s] +'}") // hamis privát logikai érték érvénytelenAlphabeticStringResult; @Value ("# {someBean.someValue egyezik a '\ d +'}" ") // true értékkel, ha a someValue csak számjegyeket tartalmaz magán boolean validNumericValue;

2.6. Hozzáférés Lista és Térkép Tárgyak

A SpEL segítségével hozzáférhetünk bármelyik tartalmához Térkép vagy Lista a kontextusban. Új babot fogunk létrehozni dolgozókTartó amely egyes munkavállalókról és fizetéseikről információkat tárol a Lista és a Térkép:

@Component ("workerHolder") nyilvános osztály WorkersHolder {private List dolgozók = new LinkedList (); privát térkép fizetésByWorkers = új HashMap (); public WorkersHolder () {dolgozók.add ("John"); dolgozók.add ("Susie"); munkások.add ("Alex"); munkások.add ("George"); fizetésByWorkers.put ("John", 35000); fizetésByWorkers.put ("Susie", 47000); fizetésByWorkers.put ("Alex", 12000); fizetésByWorkers.put ("George", 14000); } // Getters and setters}

Most a SpEL segítségével elérhetjük a gyűjtemények értékeit:

@Value ("# {workerHolder.salaryByWorkers ['John']}") // 35000 Integer privát johnSalary; @Value ("# {workersHolder.salaryByWorkers ['George']}") // 14000 privát egész szám georgeSalary; @Value ("# {workerHolder.salaryByWorkers ['Susie']}") // 47000 Integer privát susieSalary; @Value ("# {workerHolder.workers [0]}") // John private String firstWorker; @Value ("# {workerHolder.workers [3]}") // George privát karakterlánc lastWorker; @Value ("# {workerHolder.workers.size ()}") // 4 privát egész számOfWorkers;

3. Használja a tavaszi konfigurációban

3.1. Babra utalás

Ebben a példában megvizsgáljuk, hogyan lehet a SpEL-t XML-alapú konfigurációban használni. Kifejezések használhatók bab vagy babmezők / módszerek hivatkozására. Tegyük fel például, hogy a következő osztályok vannak:

public class Engine {private int capacity; privát int horsePower; private int numberOfCylinders; // Getters and setters} public class Car {private String make; privát int modell; saját Motor motor; privát int horsePower; // Getters and setters}

Most létrehozunk egy alkalmazáskörnyezetet, amelyben kifejezéseket használunk az értékek injektálására:

Vessen egy pillantást a someCar bab. A motor és lóerő mezői someCar olyan kifejezéseket használjon, amelyek bab hivatkozások a motor bab és lóerő mező ill.

Ha annotáció alapú konfigurációkkal szeretné ugyanezt megtenni, használja a @Value („# {kifejezés}”) annotáció.

3.2. Operátorok használata a konfigurációban

A cikk első szakaszának minden operátora használható XML és annotáció alapú konfigurációkban. Ne feledje azonban, hogy XML alapú konfigurációban nem használhatjuk a „<“ sarok zárójel operátort. Ehelyett az alfabetikus álneveket kell használnunk, mint pl lt (kevesebb, mint) vagy le (kevesebb vagy egyenlő). Az annotáció alapú konfigurációk esetében nincsenek ilyen korlátozások.

nyilvános osztály SpelOperators {privát logikai egyenlő; privát logikai notEqual; privát boolean nagyobbThanOrEqual; privát logikai és; privát logikai vagy; privát String addString; // Getters and setters
 @Orride public String toString () {// toString amely tartalmazza az összes mezőt}

Most hozzáadunk egy spelOperátorok bab az alkalmazás kontextusához:

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

Ha lekérjük azt a babot a kontextusból, akkor ellenőrizhetjük, hogy az értékeket megfelelően injektáltuk-e:

ApplicationContext context = új ClassPathXmlApplicationContext ("applicationContext.xml"); SpelOperators spelOperators = (SpelOperators) context.getBean ("spelOperators"); 

Itt láthatjuk a Sztring a metódusa spelOperátorok bab:

[egyenlő = igaz, nemEqual = hamis, nagyobbThanOrEqual = igaz, és = igaz, vagy = igaz, addString = Néhány, egyesek által gyártott modell] 

4. Kifejezések elemzése programozottan

Időnként érdemes a kifejezéseket a konfiguráció kontextusán kívül elemezni. Szerencsére ez lehetséges, felhasználva SpelExpressionParser. Használhatunk minden olyan operátort, amelyet az előző példákban láttunk, de zárójel és hash szimbólum nélkül kell használnunk őket. Vagyis ha egy kifejezést akarunk használni a + operátor, amikor a Spring konfigurációban használják, a szintaxis #{1 + 1}; ha konfiguráción kívül használjuk, a szintaxis egyszerűen 1 + 1.

A következő példákban a Autó és Motor az előző szakaszban meghatározott bab.

4.1. Használata ExpressionParser

Nézzünk meg egy egyszerű példát:

ExpressionParser expressionParser = new SpelExpressionParser (); Expression kifejezés = expressionParser.parseExpression ("'Bármely karakterlánc'"); Karakterlánc eredménye = (String) kifejezés.getValue (); 

ExpressionParser felelős a kifejezés karaktersorozatainak elemzéséért. Ebben a példában a SpEL elemző egyszerűen kiértékeli a karakterláncot „Bármilyen húr” mint kifejezés. Nem meglepő, hogy az eredmény az lesz „Bármilyen húr”.

Csakúgy, mint a SpEL használatakor a konfigurációban, használhatjuk metódusok hívására, tulajdonságok elérésére vagy konstruktorok hívására.

Kifejezés kifejezés = expressionParser.parseExpression ("'Bármely karakterlánc.length ()"); Egész eredmény = (Egész) kifejezés.getValue ();

Ezenkívül ahelyett, hogy közvetlenül a literálon működnénk, hívhatnánk a konstruktort:

Kifejezés kifejezés = expressionParser.parseExpression ("új karakterlánc ('Bármely karakterlánc'). Hossz ()");

Hozzáférhetünk a bájtokat tulajdona Húr osztály, ugyanúgy, ami a sztring byte [] ábrázolását eredményezi:

Kifejezés kifejezés = kifejezésParser.parseExpression ("'Bármely karakterlánc.bájt"); bájt [] eredmény = (bájt []) kifejezés.getValue ();

Láncolhatunk metódushívásokat, csakúgy, mint a normál Java kódban:

Kifejezés kifejezés = kifejezésParser.parseExpression ("'Bármely karakterlánc.replace (\" \ ", \" \ "). Hossz ()"); Egész eredmény = (Egész) kifejezés.getValue ();

Ebben az esetben az eredmény 9 lesz, mert a szóközt helyettesítettük az üres karakterlánccal. Ha nem akarjuk leadni a kifejezés eredményét, használhatjuk az általános módszert T getValue (Osztály kívánatos eredményTípus), amelyben megadhatjuk a kívánt osztálytípust, amelyet vissza akarunk küldeni. Vegye figyelembe, hogy EvaluationException dobni fog, ha a visszaküldött értéket nem lehet leadni wishResultType:

Egész eredmény = kifejezés.getValue (Egész szám.osztály);

A legelterjedtebb kifejezés egy olyan kifejezési karaktersorozat biztosítása, amelyet egy adott objektumpéldányhoz értékelnek:

Autóautó = új Autó (); car.setMake ("Jó gyártó"); car.setModel ("3. modell"); car.setYearOfProduction (2014); ExpressionParser expressionParser = new SpelExpressionParser (); Kifejezés kifejezés = kifejezésParser.parseExpression ("modell"); EvaluationContext context = új StandardEvaluationContext (autó); Karakterlánc eredménye = (String) kifejezés.getValue (kontextus);

Ebben az esetben az eredmény megegyezik a modell mező autó tárgy, "3. modell“. A StandardEvaluationContext osztály meghatározza, hogy melyik objektum alapján értékelik a kifejezést.

A kontextus objektum létrehozása után nem változtatható meg. StandardEvaluationContext felépítése drága, és ismételt használat során gyorsítótárazott állapotot épít fel, amely lehetővé teszi a későbbi kifejezés kiértékelések gyorsabb végrehajtását. A gyorsítótár miatt jó az újrafelhasználás StandardEvaluationContext ahol lehetséges, ha a gyökér objektum nem változik.

Ha azonban a gyökér objektumot ismételten megváltoztatjuk, használhatjuk az alábbi példában bemutatott mechanizmust:

Kifejezés kifejezés = kifejezésParser.parseExpression ("modell"); Karakterlánc eredménye = (String) kifejezés.getValue (autó);

Itt hívjuk a getValue metódus argumentummal, amely azt az objektumot reprezentálja, amelyre SpEL kifejezést szeretnénk alkalmazni. Használhatjuk a generikusat is getValue módszer, csakúgy, mint korábban:

Kifejezés kifejezés = kifejezésParser.parseExpression ("yearOfProduction> 2005"); logikai eredmény = kifejezés.getValue (autó, logikai.osztály);

4.2. Használata ExpressionParser az érték beállításához

Használni a érték beállítása módszer a Kifejezés A kifejezés elemzésével visszaküldött objektum értékeket állíthatunk be az objektumokon. A SpEL gondoskodik a típusátalakításról. Alapértelmezés szerint a SpEL használja org.springframework.core.convert.ConversionService. Készíthetünk saját egyedi átalakítót a típusok között. ConversionService a generikusok tisztában vannak-e, ezért a generikusokkal együtt is használható. Vizsgáljuk meg, hogyan használhatjuk a gyakorlatban:

Autóautó = új Autó (); car.setMake ("Jó gyártó"); car.setModel ("3. modell"); car.setYearOfProduction (2014); CarPark carPark = új CarPark (); carPark.getCars (). add (autó); StandardEvaluationContext context = új StandardEvaluationContext (carPark); ExpressionParser expressionParser = new SpelExpressionParser (); kifejezésParser.parseExpression ("autók [0] .model"). setValue (kontextus, "Egyéb modell");

A kapott autó objektumnak meglesz modellMás modell”, Amely megváltozott3. modell“.

4.3. Elemző konfigurációja

A következő példában a következő osztályt fogjuk használni:

nyilvános osztályú CarPark {magánlista autók = new ArrayList (); // Getter and setter}

Konfigurálni lehet ExpressionParser felhívva a konstruktort a-val SpelParserConfiguration tárgy. Például, ha megpróbáljuk hozzáadni autó objektum a autók tömbje Parkoló osztály az értelmező konfigurálása nélkül, egy ilyen hibát kapunk:

EL1025E: (4. tétel): A gyűjtemény '0' elemet tartalmaz, a '0' index érvénytelen

Megváltoztathatjuk az elemző viselkedését, hogy lehetővé tegye az elemek automatikus létrehozását, ha a megadott index null (autoGrowNullReferences, a konstruktor első paramétere), vagy automatikusan növelni egy tömböt vagy listát a kezdeti méreten túli elemek befogadására (autoGrowCollections, a második paraméter).

SpelParserConfiguration config = new SpelParserConfiguration (true, true); StandardEvaluationContext context = új StandardEvaluationContext (carPark); ExpressionParser expressionParser = new SpelExpressionParser (config); kifejezésParser.parseExpression ("autók [0]"). setValue (kontextus, autó); Autó eredmény = carPark.getCars (). Get (0);

A kapott autó objektum egyenlő lesz a autó objektum, amelyet a autók tömbje parkoló objektum az előző példából.

5. Következtetés

A SpEL egy hatékony, jól támogatott kifejezésnyelv, amely a Spring portfólió összes termékében használható. Használható a Spring alkalmazások konfigurálására vagy értelmezők írására általánosabb feladatok végrehajtására bármely alkalmazásban.

Az ebben a cikkben szereplő kódminták a linkelt GitHub-tárházban érhetők el.