Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
java_weekendowa_20221008
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Patryk Czarnik
java_weekendowa_20221008
Commits
e8a306e9
Commit
e8a306e9
authored
Nov 27, 2022
by
Patryk Czarnik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ProductController - GET,PUT,POST,DELETE
parent
8d9a31c6
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
116 additions
and
0 deletions
+116
-0
ProductController.java
...estSpring/src/main/java/sklep/rest/ProductController.java
+116
-0
No files found.
PC32-RestSpring/src/main/java/sklep/rest/ProductController.java
View file @
e8a306e9
package
sklep
.
rest
;
package
sklep
.
rest
;
import
java.math.BigDecimal
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Optional
;
import
java.util.Optional
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.dao.EmptyResultDataAccessException
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.DeleteMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.PutMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.server.ResponseStatusException
;
import
org.springframework.web.server.ResponseStatusException
;
import
sklep.model.Product
;
import
sklep.model.Product
;
import
sklep.photo.PhotoUtil
;
import
sklep.repository.ProductRepository
;
import
sklep.repository.ProductRepository
;
/* RestController to jest taki Controller, który nie używa szablonów, tylko wyniki metod odsyła w treści odpowiedzi do klienta.
* Inaczej mówiąc działa tak, jakby każda metoda miała @ResponseBody.
*
* Najczęściej na poziomie klasy umieszcza się też @RequestMapping z ogólnym adresem, pod którym działa cała ta klasa.
* Metody wewnątrz mogą mieć podany "dalszy ciąg adresu".
*/
@RestController
@RestController
@RequestMapping
(
"/products"
)
@RequestMapping
(
"/products"
)
public
class
ProductController
{
public
class
ProductController
{
@Autowired
@Autowired
private
ProductRepository
productRepository
;
private
ProductRepository
productRepository
;
@Autowired
private
PhotoUtil
photoUtil
;
@GetMapping
@GetMapping
public
List
<
Product
>
wszystkieProdukty
()
{
public
List
<
Product
>
wszystkieProdukty
()
{
return
productRepository
.
findAll
();
return
productRepository
.
findAll
();
...
@@ -35,4 +51,104 @@ public class ProductController {
...
@@ -35,4 +51,104 @@ public class ProductController {
}
}
}
}
// Przykład metody, która "wchodzi w szczegóły rekordu".
// To nie jest częsta praktyka, ale pokazuję to dla lepszego zrozumienia idei REST - adresy URL odpowiadają logicznej strukturze danych.
@GetMapping
(
"/{id}/price"
)
public
BigDecimal
getPrice
(
@PathVariable
Integer
id
)
{
Optional
<
Product
>
product
=
productRepository
.
findById
(
id
);
if
(
product
.
isPresent
())
{
return
product
.
get
().
getPrice
();
}
else
{
throw
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
);
}
}
/*
* Operacja PUT służy do zapisania danych POD PODANYM ADRESEM.
* Na przykład PUT products/2/price z wartością 100 powinno ustawić w produkcie nr 2 cenę 100.
* Jeśli PUT zadziała, to następnie GET wysłany pod ten sam adres powinien odczytać te same dane,
* które PUT zapisał (być może w innym formacie - to inny temat)
*
* PUT najczęściej jest używany do aktualizacji istniejących danych
* (pojedynczych wartości albo całych rekordów), ale może być też użyty do
* zapisania nowych danych. To, co najważniejsze, to fakt, że PUT zapisuje dane
* pod konkretnym adresem, do którego jest wysyłany.
*
* Aby odczytać dane, które przysłał klient, metoda ma jeden parametr oznaczony @RequestBody.
* To do tego parametru Spring przekaże dane odczytane z "body" zapytania.
*/
@PutMapping
(
"/{id}/price"
)
public
void
setPrice
(
@PathVariable
Integer
id
,
@RequestBody
BigDecimal
newPrice
)
{
Optional
<
Product
>
product
=
productRepository
.
findById
(
id
);
if
(
product
.
isPresent
())
{
Product
realProduct
=
product
.
get
();
realProduct
.
setPrice
(
newPrice
);
productRepository
.
save
(
realProduct
);
}
else
{
throw
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
);
}
}
/*
* PUT może również służyć do zapisania całego rekordu, ale zwn, że musi być
* skierowany pod ten adres, pod którym rekord zostanie faktycznie zapisany, w
* praktyce PUT jest uzywany do aktualizacji rekordów (UPDATE).
*
* Aby w aplikacji Springowej, w której jest włączone security, działały zapytania POST i PUT,
* trzeba wyłączyć zabezpieczenie "CSRF":
* .and().csrf().disable()
*/
@PutMapping
(
"/{id}"
)
public
void
update
(
@PathVariable
(
"id"
)
Integer
productId
,
@RequestBody
Product
product
)
{
// Aby mieć pewność, że zapisujemu produkt o typ ID, wpisuję productId z URL-a.
// Ewentualnie możnaby jeszcze sprawdzić czy rekord istnieje, czy ID się zgadza
// i jeśli coś jest nie tak, to wyrzucić wyjątek.
product
.
setProductId
(
productId
);
productRepository
.
save
(
product
);
}
/*
* POST jest najbardziej ogólną metodą HTTP; oznacza, że klient
* "wysyła jakieś dane na serwer", a serwer odsyła jakąś odpowiedź.
* W zasadzie POST może służyć do wszystkiego.
*
* W praktyce POST bardzo często służy do dodawania nowych rekordów, ponieważ
* gdy tworzymy nowy rekord, to nie znamy z góry jego ID i nie wiemy pod jakim
* URL-em zostanie zapisany (nie da się więc użyć PUT). Stąd wzięła REST-owa
* konwencja, że aby dodać nowy rekord do katalogu, wysyła się POST z danymi
* tego rekordu pod ogólny adres całego katalogu.
*/
@PostMapping
public
Product
insert
(
@RequestBody
Product
product
)
{
// Aby mieć pewność, że zapytanie tworzy nowy rekord, ustawiam productId na null.
product
.
setProductId
(
null
);
productRepository
.
save
(
product
);
/* Operacja save (a wewnętrznie persist z Hibernate) spowoduje ustawienie nowego ID w obiekcie.
* Warto taką informację przekazać klientowi. Można:
* 1) odesłać uzupełniony rekord (i tak zrobimy tutaj),
* 2) odesłać "małego JSON-a" z informacją o tym ID
* (i innymi informacjami, które serwer chce przekazać klientowi)
* 3) tylko nagłówek Location z URL-em nowego rekordu (to zobaczymy w wersji JAX-RS).
*/
return
product
;
}
@DeleteMapping
(
"/{id}"
)
public
void
delete
(
@PathVariable
(
"id"
)
Integer
productId
)
{
try
{
productRepository
.
deleteById
(
productId
);
}
catch
(
EmptyResultDataAccessException
e
)
{
throw
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
,
"Brak produktu nr "
+
productId
);
}
}
/* Większość komunikacji w usługach REST odbywa się w formacie JSON,
* ale czasami używany jest też format XML,
* a dla niektórych danych stosujemy bezpośrednio jakiś format specjalny, np. PNG, JPG dla obrazów, PDF dla wydruków itp.
*/
@GetMapping
(
path
=
"/{id}/photo"
,
produces
=
"image/jpeg"
)
public
byte
[]
getPhoto
(
@PathVariable
(
"id"
)
int
productId
)
{
return
photoUtil
.
readBytes
(
productId
);
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment