REST Dotazovací jazyk - implementácia alebo prevádzka

ODPOČINOK Najlepšie

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ Tento článok je súčasťou série: • Dotazovací jazyk REST s kritériami Spring a JPA

• Dotazovací jazyk REST so špecifikáciami JPA Spring Data

• REST dotazovací jazyk s Spring Data JPA a Querydsl

• REST Query Language - Pokročilé vyhľadávacie operácie

• REST Query Language - Implementácia ALEBO prevádzka (aktuálny článok) • REST Query Language s RSQL

• REST Query Language s webovou podporou Querydsl

1. Prehľad

V tomto rýchlom článku rozšírime rozšírené vyhľadávacie operácie, ktoré sme implementovali v predchádzajúcom článku, a zahrnieme ich Kritériá vyhľadávania založené na operácii OR do nášho dotazovacieho jazyka REST API.

2. Implementačný prístup

Predtým, než všetky kritériá v Vyhľadávanie parameter dopytu tvorený predikátmi zoskupenými iba operátorom AND. Zmeňme to.

Mali by sme byť schopní implementovať túto funkciu buď ako jednoduchú, rýchlu zmenu existujúceho prístupu, alebo úplne novú.

Jednoduchým prístupom označíme kritériá tak, aby naznačovali, že je potrebné ich kombinovať pomocou operátora OR.

Napríklad tu je adresa URL na testovanie API pre „meno ALEBO priezvisko “:

// localhost: 8080 / users? search = meno: john, 'priezvisko: laň

Upozorňujeme, že sme označili kritériá priezvisko jedinou citáciou na odlíšenie. Tento predikát pre operátor OR zachytíme v našom objekte hodnoty kritérií - Kritériá SpecSearch:

public SpecSearchCriteria (String orPredicate, String key, SearchOperation operation, Object value) {super (); this.orPredicate = orPredicate! = null && orPredicate.equals (SearchOperation.OR_PREDICATE_FLAG); this.key = kľúč; this.operation = prevádzka; this.value = value; }

3. UserSpecificationBuilder Zlepšenie

Teraz poďme upraviť náš nástroj na tvorbu špecifikácií, UserSpecificationBuilder, pri konštrukcii vziať do úvahy kritériá kvalifikované podľa ALEBO Špecifikácia:

public Specification build () {if (params.size () == 0) {return null; } Výsledok špecifikácie = nová Špecifikácia používateľa (params.get (0)); pre (int i = 1; i <params.size (); i ++) {result = params.get (i) .isOrPredicate ()? Specification.where (result) .or (new UserSpecification (params.get (i))): Specification.where (result) .and (new UserSpecification (params.get (i))); } vrátiť výsledok; }

4. UserController Zlepšenie

Nakoniec nastavíme nový koncový bod REST v našom ovládači, aby sme mohli túto funkciu vyhľadávania používať s operátorom OR. Vylepšená logika syntézy extrahuje špeciálny príznak, ktorý pomáha pri identifikácii kritérií s operátorom OR:

@GetMapping ("/ users / espec") @ResponseBody public List findAllByOrPredicate (@RequestParam String search) {Specification spec = resolveSpecification (search); vrátiť dao.findAll (spec); } chránená Špecifikácia resolveSpecification (String searchParameters) {UserSpecificationsBuilder builder = nový UserSpecificationsBuilder (); Reťazec operationSetExper = Joiner.on ("|") .join (SearchOperation.SIMPLE_OPERATION_SET); Pattern pattern = Pattern.compile ("(\ p {Punct}?) (\ w +?) (" + OperationSetExper + ") (\ p {Punct}?) (\ w +?) (\ p { Bod}?), "); Matcher matcher = pattern.matcher (searchParameters + ","); while (matcher.find ()) {builder.with (matcher.group (1), matcher.group (2), matcher.group (3), matcher.group (5), matcher.group (4), matcher. skupina (6)); } návrat builder.build (); }

5. Živý test s ALEBO Stav

V tomto príklade živého testu budeme s novým koncovým bodom API hľadať používateľov podľa mena „john“ ALEBO priezviska „doe“. Všimnite si tento parameter priezvisko má jedinú citáciu, ktorá ho kvalifikuje ako „predikát ALEBO“:

private String EURL_PREFIX = "// localhost: 8082 / spring-rest-full / auth / users / espec? search ="; @Test public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect () {Response response = givenAuth (). Get (EURL_PREFIX + "firstName: john, 'lastName: doe"); Výsledok reťazca = response.body (). AsString (); assertTrue (result.contains (userJohn.getEmail ())); assertTrue (result.contains (userTom.getEmail ())); }

6. Test vytrvalosti pomocou ALEBO Stav

Teraz vykonajme ten istý test, ktorý sme vykonali vyššie, na úrovni perzistencie pre používateľov s menom „john“ ALEBO priezviskom „srnka“:

@Test public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect () {UserSpecificationsBuilder builder = nový UserSpecificationsBuilder (); SpecSearchCriteria spec = new SpecSearchCriteria ("firstName", SearchOperation.EQUALITY, "john"); SpecSearchCriteria spec1 = nové SpecSearchCriteria ("'", "priezvisko", SearchOperation.EQUALITY, "laň"); Zoznam výsledkov = úložisko .findAll (builder.with (spec) .with (spec1) .build ()); assertThat (výsledky, hasSize (2)); assertThat (userJohn, isIn (výsledky)); assertThat (userTom, isIn (výsledky)); }

7. Alternatívny prístup

V alternatívnom prístupe by sme mohli vyhľadávací dopyt poskytnúť skôr ako úplný KDE klauzula SQL dotazu.

Napríklad tu je adresa URL pre zložitejšie vyhľadávanie podľa krstné meno a Vek:

// localhost: 8080 / users? search = (meno: john OR meno: tom) A vek> 22

Upozorňujeme, že jednotlivé kritériá, operátory a zoskupovacie zátvorky sme oddelili medzerou, aby sme vytvorili platný infixový výraz.

Poďme analyzovať infixový výraz s a CriteriaParser. Náš CriteriaParser rozdelí daný výraz infix na tokeny (kritériá, zátvorky, operátory AND a OR) a pre rovnaké vytvorí výraz postfix:

public Deque parse (String searchParam) {Deque output = new LinkedList (); Deque stack = new LinkedList (); Arrays.stream (searchParam.split ("\ s +")). ForEach (token -> {if (ops.containsKey (token)) {while (! Stack.isEmpty () && isHigerPrecedenceOperator (token, stack.peek () )) {output.push (stack.pop (). equalsIgnoreCase (SearchOperation.OR_OPERATOR)? SearchOperation.OR_OPERATOR: SearchOperation.AND_OPERATOR);} stack.push (token.equalsIgnoreCase (SearchOperation.OR_OPERATOR)? );} else if (token.equals (SearchOperation.LEFT_PARANTHESIS)) {stack.push (SearchOperation.LEFT_PARANTHESIS);} else if (token.equals (SearchOperation.RIGHT_PARANTHESIS)) {while (! stack.peek (). equals ( SearchOperation.LEFT_PARANTHESIS)) {output.push (stack.pop ());} stack.pop ();} else {matcher matcher = SpecCriteraRegex.matcher (token); while (matcher.find ()) {output.push ( new SpecSearchCriteria (matcher.group (1), matcher.group (2), matcher.group (3), matcher.group (4), matcher.group (5))));}}}); while (! stack.isEmpty ()) {output.push (stack.pop ()); } návrat výstup; }

Pridajme do nášho nástroja na tvorbu špecifikácií novú metódu, GenericSpecificationBuilder, na zostavenie hľadania Špecifikácia z výrazu postfix:

 verejné zostavenie špecifikácie (Deque postFixedExprStack, funkcia prevodník) {Deque specStack = nový LinkedList (); while (! postFixedExprStack.isEmpty ()) {Object mayBeOperand = postFixedExprStack.pollLast (); if (! (mayBeOperand instanceof String)) {specStack.push (converter.apply ((SpecSearchCriteria) mayBeOperand)); } else {Špecifikácia operand1 = specStack.pop (); Špecifikácia operand2 = specStack.pop (); if (mayBeOperand.equals (SearchOperation.AND_OPERATOR)) {specStack.push (Specification.where (operand1) .and (operand2)); } else if (mayBeOperand.equals (SearchOperation.OR_OPERATOR)) {specStack.push (Specification.where (operand1) .or (operand2)); }}} vrátiť specStack.pop ();

Na záver pridajme do nášho ďalší koncový bod REST UserController analyzovať zložitý výraz s novým CriteriaParser:

@GetMapping ("/ users / spec / adv") @ResponseBody public List findAllByAdvPredicate (@RequestParam String search) {Specification spec = resolveSpecificationFromInfixExpr (search); vrátiť dao.findAll (spec); } chránená špecifikácia resolveSpecificationFromInfixExpr (reťazec searchParameters) {CriteriaParser parser = nový CriteriaParser (); GenericSpecificationsBuilder specBuilder = nový GenericSpecificationsBuilder (); vrátiť specBuilder.build (parser.parse (searchParameters), UserSpecification :: new); }

8. Záver

V tomto tutoriáli sme vylepšili náš dotazovací jazyk REST o schopnosť vyhľadávať pomocou operátora OR.

Celú implementáciu tohto článku nájdete v projekte GitHub. Toto je projekt založený na Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.

Ďalšie » REST dotazovací jazyk s RSQL « Predchádzajúci dotazovací jazyk REST - Operácie pokročilého vyhľadávania REST dole

Práve som oznámil nové Naučte sa jar kurz zameraný na základy jari 5 a Spring Boot 2:

>> SKONTROLUJTE KURZ