Ez a REST áttekintésének utolsó része. Az előző részekben a következőkről volt szó:
Projekt létrehozása
Ebben a részben egy kis RESTful alkalmazást fogunk létrehozni a Spring Boot segítségével. Alkalmazásunk CRUD (Create, Read, Update, Delete) műveleteket valósít meg az ügyfeleken az áttekintés előző részében található példából . Kezdésként létrehozunk egy új Spring Boot alkalmazást a menün keresztül: Fájl -> Új -> Projekt... A megnyíló ablakban válassza ki a Spring Initializr-t és adja meg a Project SDK-t: Kattintson a "Next" gombra. A következő ablakban adja meg a "Maven Project" projekttípust, adja meg a "Csoportot" és az "Artifactot": Kattintson a "Next" gombra. A következő ablakban ki kell választanunk a projekthez szükséges Spring Framework komponenseket. A tavaszi web elég lesz nekünk: Kattintson a "Tovább" gombra. Most már csak meg kell adni a projekt nevét és helyét a fájlrendszerben: Kattintson a "Befejezés" gombra. A projekt elkészült, és most láthatjuk a szerkezetét: az IDEA létrehozta számunkra a Maven telepítési leírót (pom.xml) és az alkalmazás fő osztályát ( ).RestExampleApplication
Így néznek ki:
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.codegym.lessons/groupId>
<artifactId>rest_example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rest_example</name>
<description>REST example project</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
RestExampleApplication:
@SpringBootApplication
public class RestExampleApplication {
public static void main(String[] args) {
SpringApplication.run(RestExampleApplication.class, args);
}
}
REST funkció létrehozása
Alkalmazásunk ügyfélkezelési rendszer. Tehát az első dolog, amit tennünk kell, egy ügyfél entitás létrehozása. Ez egy POJO (sima régi Java objektum) osztály lesz. Hozzon létre egymodel
csomagot a com.codegym.lessons.rest_example
csomagon belül. model
A csomagon belül hozza létre a következőt Customer
:
public class Customer {
private Integer id;
private String name;
private String email;
private String phone;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
}
A szolgáltatás CRUD műveleteket hajt végre az ügyfeleken. A következő lépés egy olyan szolgáltatás létrehozása, amely végrehajtja ezeket a műveleteket. A csomagban com.codegym.lessons.rest_example
hozzon létre egy service
csomagot. És ezen belül hozzon létre egy CustomerService
felületet. Íme az interfész kód megjegyzésekkel:
public interface CustomerService {
/**
* Creates a new customer
* @param customer - Customer to be created
*/
void create(Customer customer);
/**
* Returns a list of all existing customers
* @return List of customers
*/
List<Customer> readAll();
/**
* Returns a customer based on its ID
* @param id - Customer ID
* @return - Customer object with the given ID
*/
Customer read(int id);
/**
* Updates the customer with the given ID,
* according to the passed customer
* @param customer - Customer to use to update the data
* @param id - ID of the customer you want to update
* @return - true if the data has been updated, otherwise false
*/
boolean update(Customer customer, int id);
/**
* Deletes the customer with the given ID
* @param id - ID of the customer to be deleted
* @return - true if the customer was deleted, otherwise false
*/
boolean delete(int id);
}
Ezután ezt a felületet kell megvalósítanunk. Most a Map<Integer, Customer>
fog tárolni ügyfeleink. A térkép kulcsai az ügyfél-azonosítók, az értékek pedig maguk az ügyfelek lesznek. Ez azért történik, hogy ne terheljük túl ezt a példát egy valódi adatbázissal való munkavégzés sajátosságaival. A jövőben azonban írhatunk majd egy újabb implementációt az interfésznek, amivel valódi adatbázishoz lehet kapcsolódni. A csomagban service
hozza létre a felület megvalósítását CustomerService
:
@Service
public class CustomerServiceImpl implements CustomerService {
// Customer repository
private static final Map<Integer, Customer> CUSTOMER_REPOSITORY_MAP = new HashMap<>();
// Variable for generating a customer ID
private static final AtomicInteger CUSTOMER_ID_HOLDER = new AtomicInteger();
@Override
public void create(Customer customer) {
final int customerId = CUSTOMER_ID_HOLDER.incrementAndGet();
customer.setId(customerId);
CUSTOMER_REPOSITORY_MAP.put(customerId, customer);
}
@Override
public List<Customer> readAll() {
return new ArrayList<>(CUSTOMER_REPOSITORY_MAP.values());
}
@Override
public Customer read(int id) {
return CUSTOMER_REPOSITORY_MAP.get(id);
}
@Override
public boolean update(Customer customer, int id) {
if (CUSTOMER_REPOSITORY_MAP.containsKey(id)) {
customer.setId(id);
CUSTOMER_REPOSITORY_MAP.put(id, customer);
return true;
}
return false;
}
@Override
public boolean delete(int id) {
return CUSTOMER_REPOSITORY_MAP.remove(id) != null;
}
}
A @Service
kommentár azt mondja tavasznak, hogy ez az osztály szolgáltatás. Ez egy speciális osztálytípus, amely bizonyos üzleti alkalmazások logikáját valósítja meg. Ezt követően ennek az annotációnak köszönhetően a Spring a függőségi befecskendezés segítségével biztosítja számunkra ennek az osztálynak a példányát minden olyan helyen, ahol szükség van rá. Most itt az ideje egy vezérlő létrehozásának. Ez egy speciális osztály, ahol megvalósítjuk a végpontokhoz (URI) küldött klienskérések feldolgozásának logikáját. Hogy mindezt világosabbá tegyük, ezt az osztályt fokozatosan hozzuk létre. Először hozza létre magát az osztályt, és adjon hozzá egy függőséget a következőhöz CustomerService
:
@RestController
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
}
Magyarázzuk el a megjegyzéseket: @RestController közli a Spring-rel, hogy ez az osztály egy REST vezérlő. Más szavakkal, ez az osztály valósítja meg az ügyfélkérések feldolgozásának logikáját. Az @Autowired azt mondja Springnek, hogy hozzá kell adni egy függőséget. A felületet átadjuk CustomerService
a konstruktornak. Korábban ennek a szolgáltatásnak a megvalósítását jelöltük a megjegyzéssel @Service
, most pedig a Spring átadhatja ennek a megvalósításnak egy példányát a vezérlő konstruktorának. Ezután minden egyes vezérlő módszert implementálunk a CRUD műveletek kezelésére. Kezdjük a létrehozási művelettel. Ehhez írunk egy create
metódust:
@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
customerService.create(customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
Elemezzük ezt a módszert: ez @PostMapping(value = "/customers")
azt jelenti, hogy ez a módszer feldolgozza a „/customers” címre küldött POST kéréseket. A metódus egy ResponseEntity<?>
. Az A ResponseEntity
egy speciális osztály a válaszok visszaküldésére. Később egy HTTP állapotkód visszaküldésére fogjuk használni az ügyfélnek. A módszernek van @RequestBody Customer customer
paramétere. Ennek a paraméternek az értéke a kérés törzséből származik. Az @RequestBody
annotáció ezt jelzi. create()
A metódus törzsén belül a korábban létrehozott szolgáltatáson meghívjuk a metódust és átadjuk a paraméterekben kapott ügyfélkontrollernek. Ezután visszaállítjuk a "201 Created" állapotot egy új objektum létrehozásával ResponseEntity
és a megfelelő HttpStatus
enum mező átadásával. Ezt követően megvalósítjuk aread
művelet: Először is végrehajtjuk a műveletet, hogy megkapjuk az összes elérhető ügyfél listáját:
@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
final List<Customer> customers = customerService.readAll();
return customers != null && !customers.isEmpty()
? new ResponseEntity<>(customers, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Merüljünk el: @GetMapping(value = "/customers")
— itt minden hasonló a @PostMapping
kommentárhoz, de most a GET kéréseket dolgozzuk fel. Ezúttal egy ResponseEntity<List<Customer>>
, és a HTTP-státusz mellett egy választörzset is adunk vissza, ami az ügyfelek listája lesz. A Spring REST vezérlőiben minden POJO-objektum és POJO-objektum-gyűjtemény, amelyek választörzsekként kerülnek visszaadásra, és automatikusan JSON-ba sorakoznak, hacsak nincs másként megadva. Ez nekünk tökéletesen megfelel. A módszeren belül szolgáltatásunkat arra használjuk, hogy minden ügyfélről listát kapjunk. Ezután, ha a lista nem nulla és nem üres, akkor aResponseEntity
osztályt, hogy visszaadja az ügyfelek listáját és a "200 OK" HTTP állapotkódot. Ellenkező esetben egyszerűen a „404 Not Found” HTTP-állapotkódot adjuk vissza. Most megvalósítjuk azt a képességet, hogy ügyfelet szerezzünk meg az azonosítójával:
@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
final Customer customer = customerService.read(id);
return customer != null
? new ResponseEntity<>(customer, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Egy új dolog itt az útvonalváltozó. A változó az URI-ban van definiálva: value = "/customers/{id}"
. Göndör zárójelben jelezzük. És megkapjuk metódusparaméterként int
az @PathVariable(name = "id")
annotáció segítségével. Ez a metódus elfogadja az URI-kra küldött kéréseket a következő formában /customers/{id}
: , ahol {id}
bármilyen számértéket jelöl. Ezt az értéket a változón keresztül továbbítják int id
a metódus paraméteréhez. A testben Customer
szolgáltatásunk segítségével megkapjuk a tárgyat és a kapott id
. Ezután a listával analóg módon vagy a "200 OK" állapotot és magát az objektumot, vagy egyszerűen a "404 Nem található" állapotot adjuk vissza, Customer
ha a rendszernek nincs ilyen ügyfele id
. Még mindig két műveletet kell végrehajtanunk: frissítést és törlést. Íme a kód ezekhez a módszerekhez:
@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
final boolean updated = customerService.update(customer, id);
return updated
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
final boolean deleted = customerService.delete(id);
return deleted
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
Ezekben a módszerekben nincs lényegében újdonság, ezért a részletes leírást kihagyjuk. Csak annyit érdemes megemlíteni, hogy a update()
metódus kezeli a PUT kéréseket ( @PutMapping
annotation), a delete()
metódus pedig a DELETE kéréseket ( DeleteMapping
annotation). Itt van a vezérlő teljes kódja:
@RestController
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@PostMapping(value = "/customers")
public ResponseEntity<?> create(@RequestBody Customer customer) {
customerService.create(customer);
return new ResponseEntity<>(HttpStatus.CREATED);
}
@GetMapping(value = "/customers")
public ResponseEntity<List<Customer>> read() {
final List<Customer> customers = customerService.readAll();
return customers != null && !customers.isEmpty()
? new ResponseEntity<>(customers, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@GetMapping(value = "/customers/{id}")
public ResponseEntity<Customer> read(@PathVariable(name = "id") int id) {
final Customer customer = customerService.read(id);
return customer != null
? new ResponseEntity<>(customer, HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@PutMapping(value = "/customers/{id}")
public ResponseEntity<?> update(@PathVariable(name = "id") int id, @RequestBody Customer customer) {
final boolean updated = customerService.update(customer, id);
return updated
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
@DeleteMapping(value = "/customers/{id}")
public ResponseEntity<?> delete(@PathVariable(name = "id") int id) {
final boolean deleted = customerService.delete(id);
return deleted
? new ResponseEntity<>(HttpStatus.OK)
: new ResponseEntity<>(HttpStatus.NOT_MODIFIED);
}
}
Ennek eredményeként projektünk felépítése a következő:
Indítás és tesztelés
Alkalmazásunk elindításához csak futtassa amain()
metódust az osztályban RestExampleApplication
. A RESTful webszolgáltatások teszteléséhez azonban további szoftvereket kell letöltenünk. A helyzet az, hogy a GET kéréseket meglehetősen egyszerű elküldeni egy közönséges böngészőből, de egy közönséges böngésző nem tud POST, PUT és DELETE kéréseket küldeni. Ne aggódjon: a Postman nevű programmal bármilyen HTTP-kérést küldhet. Itt tudod letölteni . A Postman letöltése és telepítése után megkezdjük az alkalmazás tesztelését. Ehhez nyissa meg a programot, és hozzon létre egy új kérést: Kattintson az "Új" gombra a bal felső sarokban. Ezután válassza a „Kérés” lehetőséget: Ezután adjon nevet, és mentse el. Most próbáljunk meg POST kérést küldeni a szervernek, és létrehozzuk az első ügyfelet: Több ügyfelet is létrehozunk így. Ezután módosítjuk a kérés típusát GET-re, és elküldjük a kérést a szervernek:
Összegzés
Gratulálunk! Eléggé lefedtük a REST-et. Nagy mennyiségű anyag volt, de remélhetőleg hasznos volt az Ön számára:-
Megtanultuk, mi az a REST.
-
Megtudtuk, hogyan jött létre a REST.
-
Beszéltünk ennek az építészeti stílusnak a korlátairól és alapelveiről:
- kliens-szerver architektúra
- hontalan
- gyorsítótárazás
- egységes felület
- rétegek
- igény szerinti kód (opcionális)
-
Feltérképeztük a REST által nyújtott előnyöket
-
Részletesen megvizsgáltuk, hogy a szerver és a kliens hogyan kommunikál egymással a HTTP protokollon keresztül.
-
Alaposabban megvizsgáltuk a kéréseket és válaszokat. Felbontottuk azok alkotórészeit.
-
Végül gyakorlati tapasztalatokat szerezhettünk saját kis RESTful alkalmazásunk megírásával a Spring Boot segítségével. És még azt is megtanultuk, hogyan teszteljük a Postman segítségével.
Házi feladat
Próbáld ki a következőket:- A fenti leírást követve hozza létre saját Spring Boot projektjét, és hajtsa végre ugyanazt a logikát, mint a leckében. Ismételj meg mindent pontosan.
- Indítsa el az alkalmazást.
- Töltse le és konfigurálja a Postmant (vagy bármely más kérések küldésére szolgáló eszközt, például curl).
- Tesztelje a POST és GET kéréseket a leckében leírt módon.
- Tesztelje saját maga a PUT és DELETE kéréseket.
GO TO FULL VERSION