Commit 5607adcc by Patryk Czarnik

Wydzielenie wersji JSON do oddzielnej klasy.

parent f667edea
JAX-RS - część Javy EE
Aplikacja (projekt) składa się z wielu "resource classes", z których każda obsługuje pewien rodzaj encji
np. pod adresem /products działa ta klasa RProduct, która zajmuje się obsługą produktów
a pod adresem /orders działa ROrder, która zajmuje się zamówieniami.
Przykładowa dobra (szczegółowa) dokumentacja: https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest3x/index.html
W usługach REST struktura adresów URL odpowiada logicznej strukturze danych.
Typowe jest, że * pod adresem "katalogu", np. /products , dostępna jest lista wszystkich rekordów
(lub ogólne informacje, lub jakiś sposób przeglądania - gdyby było ich za dużo do zwrócenia na raz)
a idąc dalej wgłąb ścieżki przechodzimy do "pojedynczych rekordów", np. /products/2
To od programisty (twórcy usługi) zależy jakie adresy i jakie operacje pod tymi adresami udostępnia.
Przykłady "REST API":
- https://opensource.zalando.com/restful-api-guidelines/
- https://developers.payu.com/pl/restapi.html
Implementacje JAX-RS:
* Jersey - kiedyś pod patronatem Oracle, a teraz Fundacja Eclipse - "referencyjna implementacja", używana na serwerach Glassfish oraz WebLogic, łatwo da się jej użyć w ramach aplikacji Spring Boot
* Apache CXF - kompleksowa implementacja web serwisów zarówno SOAP, jak i REST, łatwo dodać jako bibliotekę do projektów uruchomionych na Tomcat
* RestEasy - RedHat, serwery JBoss i WildFly
\ No newline at end of file
......@@ -17,18 +17,7 @@ import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
/* JAX-RS - część Javy EE
* Aplikacja (projekt) składa się z wielu "resource classes", z których każda obsługuje pewien rodzaj encji
* np. pod adresem /products działa ta klasa RProduct, która zajmuje się obsługą produktów
* a pod adresem /orders działa ROrder, która zajmuje się zamówieniami.
* Przykładowa dobra (szczegółowa) dokumentacja: https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest3x/index.html
*
* W usługach REST struktura adresów URL odpowiada logicznej strukturze danych.
* Typowe jest, że * pod adresem "katalogu", np. /products , dostępna jest lista wszystkich rekordów
* (lub ogólne informacje, lub jakiś sposób przeglądania - gdyby było ich za dużo do zwrócenia na raz)
* a idąc dalej wgłąb ścieżki przechodzimy do "pojedynczych rekordów", np. /products/2
*
* W tej klasie wejdziemy nawet do wnętrza produktów i udostępnimy osobno cenę
/* W tej klasie wejdziemy nawet do wnętrza produktów i udostępnimy osobno cenę
* /products/2/price
* W praktyce nie robi się tego zbyt często, ale tu zobaczymy jako przykład możliwości.
*
......
package sklep.rest;
import java.math.BigDecimal;
import java.util.List;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import sklep.db.DBConnection;
import sklep.db.DBException;
import sklep.db.ProductDAO;
import sklep.db.RecordNotFound;
import sklep.model.Product;
// Adnotacje @Produces i @Consumes można umieścić na poziomie klasy.
// Wszystkie metody, które coś produkują (czyli nie są void), produkują JSON-a
// (wyjątkiem jest photo - na poziomie metody można to ustawienie zmienić)
// Wszystkie metody, które coś konsumują (czyli posiadają parametr, w którym odbierane jest "ciało zapytania") konsumują JSON.
@Path("/products.json")
@Produces("application/json")
@Consumes("application/json")
public class RProductsJSON {
@GET
public List<Product> readAll() throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.readAll();
}
}
@GET
@Path("/{id}")
public Product readOne(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
return productDAO.findById(productId);
}
}
@GET
@Path("/{id}/price")
public BigDecimal getPrice(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
return product.getPrice();
}
}
@PUT
@Path("/{id}/price")
public void putPrice(@PathParam("id") int productId,
BigDecimal newPrice) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
Product product = productDAO.findById(productId);
product.setPrice(newPrice);
productDAO.update(product);
db.commit();
}
}
// (w tej klasie) - odesłanie uzupełnionego rekordu - trochę niewydajne, ale wygodne
@POST
public Product zapiszProdukt(Product product) throws DBException {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.save(product);
db.commit();
return product;
}
}
@DELETE
@Path("/{id}")
public void usun(@PathParam("id") int productId) throws DBException, RecordNotFound {
try(DBConnection db = DBConnection.open()) {
ProductDAO productDAO = db.productDAO();
productDAO.delete(productId);
db.commit();
}
}
@GET
@Produces("image/jpeg")
@Path("/{id}/photo")
public byte[] photo(@PathParam("id") int productId) throws DBException, RecordNotFound {
return PhotoUtil.readBytes(productId);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment