REST Query Language RSQL-lel

REST felső

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT Kitartás felső

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT Ez a cikk egy sorozat része: • REST Query Language with Spring and JPA Criteria

• REST lekérdezési nyelv a Spring Data JPA specifikációkkal

• REST Query Language a Spring Data JPA és a Querydsl segítségével

• REST Query Language - Speciális keresési műveletek

• REST Query Language - VAGY művelet végrehajtása

• REST Query Language RSQL-lel (aktuális cikk) • REST Query Language Querydsl webes támogatással

1. Áttekintés

A sorozat ezen ötödik cikkében a REST API Query nyelv kiépítését mutatjuk be klassz könyvtár - rsql-parser.

Az RSQL a Feed Item Query Language (FIQL) szuperkészlete - tiszta és egyszerű szűrőszintaxis a hírcsatornákhoz; így természetesen illeszkedik a REST API-ba.

2. Előkészületek

Először adjunk hozzá egy maven függőséget a könyvtárhoz:

 cz.jirutka.rsql rsql-parser 2.1.0 

És még meghatározza a fő entitást együtt fogunk dolgozni a példákban - Felhasználó:

@Entity public class User {@Id @GeneratedValue (strategy = GenerationType.AUTO) private Long id; privát karakterlánc keresztnév; privát karakterlánc vezetéknév; privát karakterlánc e-mail; privát int kor; }

3. A kérelem elemzése

Az RSQL-kifejezések belső ábrázolása csomópontok formájában történik, és a látogatói mintát használják a bemenet elemzésére.

Ezt szem előtt tartva fogjuk megvalósítani a RSQLVisitor felületet, és létrehozhatunk saját látogatói megvalósítást - CustomRsqlVisitor:

public class CustomRsqlVisitor valósítja meg az RSQLVisitor programot {privát GenericRsqlSpecBuilder építő; public CustomRsqlVisitor () {builder = new GenericRsqlSpecBuilder (); } @Override public Specification visit (AndNode csomópont, Void param) {return builder.createSpecification (csomópont); } @Override public Specification visit (OrNode csomópont, Void param) {return builder.createSpecification (csomópont); } @Override public Specification visit (ComparisonNode node, Void params) {return builder.createSecification (node); }}

Most foglalkoznunk kell a kitartással, és ezekből a csomópontokból össze kell állítanunk a lekérdezést.

A korábban használt Spring Data JPA specifikációkat fogjuk használni - és a Leírás építője ezekből a meglátogatott csomópontokból állítsuk össze a specifikációt:

public class GenericRsqlSpecBuilder {public Specification createSpecification (Node node) {if (a LogicalNode csomópont példánya) {return createSpecification ((LogicalNode) csomópont); } if (a ComparisonNode csomópont példánya) {return createSpecification ((ComparisonNode) csomópont); } return null; } public Specifikáció createSpecification (LogicalNode logikai csomópont) {List specs = logikaiNode.getChildren () .stream () .map (csomópont -> createSpecification (csomópont)) .filter (Objects :: nonNull) .collect (Collectors.toList ()); Specifikáció eredménye = specs.get (0); if (logikaiNode.getOperator () == LogicalOperator.AND) {for (int i = 1; i <specs.size (); i ++) {eredmény = Specification.where (result) .and (specs.get (i)) ; }} else if (logikaiNode.getOperator () == LogicalOperator.OR) {for (int i = 1; i <specs.size (); i ++) {eredmény = Specification.where (eredmény) .vagy (specs.get ( én)); }} visszatérési eredmény; } public Specifikáció createSpecification (ComparisonNode CompareNode) {Specifikáció eredménye = Specifikáció.where (új GenericRsqlSpecification (összehasonlításNode.getSelector (), CompareNode.getOperator (), CompareNode.getArguments ())); visszatérési eredmény; }}

Vegye figyelembe, hogyan:

  • LogicalNode egy ÉS/VAGYCsomópont és több gyermeke van
  • ComparisonNode nincs gyermeke, és tartja a Kiválasztó, operátor és érvek

Például egy „név == john" - nekünk van:

  1. Választó: „Név”
  2. Operátor: “==”
  3. Érvek:[János]

4. Készítse el az Egyéni lehetőséget Leírás

A lekérdezés összeállításakor a Leírás:

public class A GenericRsqlSpecification végrehajtja a Specifikációt {private String property; magán ComparisonOperator operátor; private List argumentumok; @Override public Predicate toPredicate (Root root, CriteriaQuery query, CriteriaBuilder builder) {List args = castArguments (root); Objektum argumentum = args.get (0); kapcsoló (RsqlSearchOperation.getSimpleOperator (operátor)) {eset EQUAL: {if (argumentum a String példánya) {return builder.like (root.get (tulajdonság), argument.toString (). csere ('*', '%')) ; } else if (argumentum == null) {return builder.isNull (root.get (tulajdonság)); } else {return builder.equal (root.get (tulajdonság), argumentum); }} eset NOT_EQUAL: {if (a String argumentum példánya) {return builder.notLike (root. get (tulajdonság), argument.toString (). csere ('*', '%')); } else if (argumentum == null) {return builder.isNotNull (root.get (tulajdonság)); } else {return builder.notEqual (root.get (tulajdonság), argumentum); }} eset GREATER_THAN: {return builder.greaterThan (root. get (tulajdonság), argumentum.toString ()); } eset GREATER_THAN_OR_EQUAL: {return builder.greaterThanOrEqualTo (root. get (tulajdonság), argument.toString ()); } case LESS_THAN: {return builder.lessThan (root. get (tulajdonság), argumentum.toString ()); } eset LESS_THAN_OR_EQUAL: {return builder.lessThanOrEqualTo (root. get (tulajdonság), argument.toString ()); } case IN: return root.get (tulajdonság) .in (érvel); eset NOT_IN: return builder.not (root.get (tulajdonság) .in (args)); } return null; } privát List castArguments (végső gyökérgyökér) {Osztálytípus = root.get (tulajdonság) .getJavaType (); List args = argumentumok.stream (). Map (arg -> {if (type.equals (Integer.class)) {return Integer.parseInt (arg);} else if (type.equals (Long.class)) {return Long.parseLong (arg);} else {return arg;}}). Gyűjt (Collectors.toList ()); return args; } // szabványos konstruktor, getter, szetter}

Figyelje meg, hogy a specifikáció miként használja a generikus gyógyszereket, és nem kapcsolódik-e egyetlen entitáshoz (például a felhasználóhoz).

Következő - itt a miénk enum “RsqlSearchOperation amely az alapértelmezett rsql-parser operátorokat tartalmazza:

nyilvános enum RsqlSearchOperation {EQUAL (RSQLOperators.EQUAL), NOT_EQUAL (RSQLOperators.NOT_EQUAL), GREATER_THAN (RSQLOperators.GREATER_THAN), GREATER_THAN_OR_EQUAL (RSQLOperators.GREATER_THAN_OR_EQUAL), LESS_THAN (RSQLOperators.LESS_THAN), LESS_THAN_OR_EQUAL (RSQLOperators.LESS_THAN_OR_EQUAL), IN (RSQLOperators. IN), NOT_IN (RSQLOperators.NOT_IN); magán ComparisonOperator operátor; privát RsqlSearchOperation (ComparisonOperator operátor) {this.operator = operátor; } public static RsqlSearchOperation getSimpleOperator (ComparisonOperator operator) {for (RsqlSearchOperation művelet: értékek ()) {if (művelet.getOperator () == operátor) {visszatérési művelet; }} return null; }}

5. Tesztelje a keresési lekérdezéseket

Most kezdjük el tesztelni új és rugalmas működésünket néhány valós forgatókönyv segítségével:

Először - inicializáljuk az adatokat:

@RunWith (SpringJUnit4ClassRunner.class) @ContextConfiguration (class = {PersistenceConfig.class}) @Transactional @TransactionConfiguration public class RsqlTest {@Autowired private UserRepository repository; private User userJohn; private User userTom; @A nyilvános void előtt init () {userJohn = new User (); userJohn.setFirstName ("john"); userJohn.setLastName ("őz"); userJohn.setEmail ("[e-mail védett]"); userJohn.setAge (22); repository.save (userJohn); userTom = új felhasználó (); userTom.setFirstName ("tom"); userTom.setLastName ("őz"); userTom.setEmail ("[e-mail védett]"); userTom.setAge (26); repository.save (userTom); }}

Most teszteljük a különböző műveleteket:

5.1. Tesztelje az egyenlőséget

A következő példában - a felhasználók alapján keresünk felhasználókat első és vezetéknév:

@Test public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect () {Csomópont rootNode = új RSQLParser (). Parse ("keresztnév == john; vezetéknév == doe"); Specifikáció spec = rootNode.accept (új CustomRsqlVisitor ()); Eredmények felsorolása = repository.findAll (spec); assertThat (userJohn, isIn (eredmények)); assertThat (userTom, nem (isIn (eredmények))); }

5.2. Test Negation

Ezután keressük meg azokat a felhasználókat, akik a keresztnév nem „john”:

@Test public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect () {Csomópont rootNode = új RSQLParser (). Parse ("keresztnév! = John"); Specifikáció spec = rootNode.accept (új CustomRsqlVisitor ()); Eredmények felsorolása = repository.findAll (spec); assertThat (userTom, isIn (eredmények)); assertThat (userJohn, nem (isIn (eredmények))); }

5.3. Tesztelje nagyobb, mint

Következő - a felhasználókat a következővel keressük meg: kor nagyobb, mint "25”:

@Test public void givenMinAge_whenGettingListOfUsers_thenCorrect () {Csomópont rootNode = új RSQLParser (). Elemzés ("életkor> 25"); Specifikáció spec = rootNode.accept (új CustomRsqlVisitor ()); Eredmények felsorolása = repository.findAll (spec); assertThat (userTom, isIn (eredmények)); assertThat (userJohn, nem (isIn (eredmények))); }

5.4. Tetszik Like

Következő - megkeressük a felhasználókat a sajátjukkal keresztnév kezdve:jo”:

@Test public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect () {Csomópont rootNode = új RSQLParser (). Parse ("keresztnév == jo *"); Specifikáció spec = rootNode.accept (új CustomRsqlVisitor ()); Eredmények felsorolása = repository.findAll (spec); assertThat (userJohn, isIn (eredmények)); assertThat (userTom, nem (isIn (eredmények))); }

5.5. Teszt BAN BEN

Következő - megkeressük a felhasználókat keresztnév az „JánosVagy „Jack“:

@Test public void givenListOfFirstName_whenGettingListOfUsers_thenCorrect () {Node rootNode = new RSQLParser (). Parse ("firstName = in = (john, jack)"); Specifikáció spec = rootNode.accept (új CustomRsqlVisitor ()); Eredmények felsorolása = repository.findAll (spec); assertThat (userJohn, isIn (eredmények)); assertThat (userTom, nem (isIn (eredmények))); }

6. UserController

Végül - kössük össze az egészet a vezérlővel:

@RequestMapping (method = RequestMethod.GET, value = "/ users") @ResponseBody public List findAllByRsql (@RequestParam (value = "search") String search) {Node rootNode = new RSQLParser (). Elemzés (keresés); Specifikáció spec = rootNode.accept (új CustomRsqlVisitor ()); return dao.findAll (spec); }

Íme egy példa URL:

// localhost: 8080 / users? search = keresztnév == jo *; életkor <25

És a válasz:

[{"id": 1, "keresztnév": "john", "vezetékNév": "őz", "e-mail": "[e-mail védett]", "kor": 24}]

7. Következtetés

Ez az oktatóanyag bemutatja, hogyan lehet egy REST API számára létrehozni egy lekérdezési / keresési nyelvet anélkül, hogy újra ki kellene találni a szintaxist, és ehelyett a FIQL / RSQL-t kell használni.

A teljes végrehajtása cikkünk megtalálható a GitHub projektben - ez egy Maven-alapú projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.

Következő » REST Queryds a Querydsl webes támogatásával « Előző REST lekérdezési nyelv - VAGY a REST művelet végrehajtása alul

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT Perzisztencia alsó

Most jelentettem be az újat Tanulj tavaszt tanfolyam, amelynek középpontjában az 5. tavasz és a tavaszi bakancs 2 alapjai állnak:

>> ELLENŐRIZZE A FOLYAMATOT

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