Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
2
20240528-BJava
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
20240528-BJava
Commits
74e47dcb
Commit
74e47dcb
authored
Jun 27, 2024
by
Patryk Czarnik
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Endpointy Restowe - ale niektóre jeszcze ie działają, bo model nieskończony
parent
fdc4b353
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
183 additions
and
6 deletions
+183
-6
PhotoUtil.java
PC33-SklepSpring/src/main/java/sklep/photo/PhotoUtil.java
+9
-1
CustomerEndpoint.java
...klepSpring/src/main/java/sklep/rest/CustomerEndpoint.java
+33
-0
OrderEndpoint.java
PC33-SklepSpring/src/main/java/sklep/rest/OrderEndpoint.java
+38
-0
ProductEndpoint.java
...SklepSpring/src/main/java/sklep/rest/ProductEndpoint.java
+101
-4
SecurityConfig.java
...epSpring/src/main/java/sklep/security/SecurityConfig.java
+2
-1
No files found.
PC33-SklepSpring/src/main/java/sklep/photo/PhotoUtil.java
View file @
74e47dcb
...
@@ -53,5 +53,13 @@ public class PhotoUtil {
...
@@ -53,5 +53,13 @@ public class PhotoUtil {
String
fileName
=
productId
+
EXT
;
String
fileName
=
productId
+
EXT
;
return
Paths
.
get
(
dir
,
fileName
);
return
Paths
.
get
(
dir
,
fileName
);
}
}
public
void
writeBytes
(
int
productId
,
byte
[]
bytes
)
{
try
{
Path
path
=
getPath
(
productId
);
Files
.
write
(
path
,
bytes
);
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
}
}
}
}
PC33-SklepSpring/src/main/java/sklep/rest/CustomerEndpoint.java
0 → 100644
View file @
74e47dcb
package
sklep
.
rest
;
import
java.util.List
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.ui.Model
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.server.ResponseStatusException
;
import
sklep.model.Customer
;
import
sklep.repository.CustomerRepository
;
@RestController
@RequestMapping
(
"/rest/customers"
)
public
class
CustomerEndpoint
{
@Autowired
private
CustomerRepository
customerRepository
;
@GetMapping
public
List
<
Customer
>
listaKlientow
(
Model
model
)
{
return
customerRepository
.
findAll
();
}
@GetMapping
(
"/{email}"
)
public
Customer
jedenKlient
(
Model
model
,
@PathVariable
(
"email"
)
String
email
)
{
return
customerRepository
.
findById
(
email
).
orElseThrow
(()
->
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
));
}
}
PC33-SklepSpring/src/main/java/sklep/rest/OrderEndpoint.java
0 → 100644
View file @
74e47dcb
package
sklep
.
rest
;
import
java.util.List
;
import
java.util.Optional
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.server.ResponseStatusException
;
import
sklep.model.Order
;
import
sklep.repository.OrderRepository
;
@RestController
@RequestMapping
(
"/rest/orders"
)
public
class
OrderEndpoint
{
@Autowired
private
OrderRepository
orderRepository
;
@GetMapping
public
List
<
Order
>
readAll
()
{
return
orderRepository
.
findAll
();
}
@GetMapping
(
"/{id}"
)
public
Order
readOne
(
@PathVariable
(
"id"
)
int
id
)
{
Optional
<
Order
>
order
=
orderRepository
.
findById
(
id
);
if
(
order
.
isPresent
())
{
return
order
.
get
();
}
else
{
throw
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
,
"Nie ma zamówienia o numerze "
+
id
);
}
}
}
PC33-SklepSpring/src/main/java/sklep/rest/ProductEndpoint.java
View file @
74e47dcb
package
sklep
.
rest
;
package
sklep
.
rest
;
import
org.springframework.http.HttpStatusCode
;
import
org.springframework.dao.EmptyResultDataAccessException
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.*
;
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.photo.PhotoUtil
;
import
sklep.repository.ProductRepository
;
import
sklep.repository.ProductRepository
;
import
java.math.BigDecimal
;
import
java.util.List
;
import
java.util.List
;
// @RestController odpowiada adnotacji @Controller z dodatkową adnotacją @ResponseBody
// @RestController odpowiada adnotacji @Controller z dodatkową adnotacją @ResponseBody
...
@@ -23,16 +25,111 @@ public class ProductEndpoint {
...
@@ -23,16 +25,111 @@ public class ProductEndpoint {
this
.
photoUtil
=
photoUtil
;
this
.
photoUtil
=
photoUtil
;
}
}
@GetMapping
@GetMapping
(
produces
=
"application/json"
)
public
List
<
Product
>
getProducts
()
{
public
List
<
Product
>
getProducts
()
{
return
productRepository
.
findAll
();
return
productRepository
.
findAll
();
}
}
@GetMapping
(
"/{id}
"
)
@GetMapping
(
path
=
"/{id}"
,
produces
=
"application/json
"
)
public
Product
getProduct
(
@PathVariable
int
id
)
{
public
Product
getProduct
(
@PathVariable
int
id
)
{
return
productRepository
.
findById
(
id
).
orElseThrow
(
return
productRepository
.
findById
(
id
).
orElseThrow
(
()
->
new
ResponseStatusException
(
HttpStatus
Code
.
valueOf
(
404
)
,
()
->
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
,
"Brak produktu o numerze "
+
id
));
"Brak produktu o numerze "
+
id
));
}
}
// Ta metoda pokazana tylko po to, aby wytłumaczyć, że struktura adresów powinna odpowiadać logicznej strukturze danych.
// W prawdziwej aplikacji raczej nie dochodzi się do poziomu pojedynczych pól. Teoretycznie można.
@GetMapping
(
path
=
"/{id}/price"
,
produces
=
"application/json"
)
public
BigDecimal
getPrice
(
@PathVariable
Integer
id
)
{
return
getProduct
(
id
).
getPrice
();
}
/*
* 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
)
{
Product
product
=
productRepository
.
findById
(
id
).
orElseThrow
(()
->
new
ResponseStatusException
(
HttpStatus
.
NOT_FOUND
));
product
.
setPrice
(
newPrice
);
productRepository
.
save
(
product
);
}
/*
* 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
.
setId
(
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
.
setId
(
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
);
}
@PutMapping
(
path
=
"/{id}/photo"
,
consumes
=
"image/jpeg"
)
public
void
uploadPhoto
(
@PathVariable
(
"id"
)
int
productId
,
@RequestBody
byte
[]
bytes
)
{
photoUtil
.
writeBytes
(
productId
,
bytes
);
}
}
}
PC33-SklepSpring/src/main/java/sklep/security/SecurityConfig.java
View file @
74e47dcb
...
@@ -12,7 +12,8 @@ public class SecurityConfig {
...
@@ -12,7 +12,8 @@ public class SecurityConfig {
@Bean
@Bean
SecurityFilterChain
configHttpSecurity
(
HttpSecurity
httpSecurity
,
HandlerMappingIntrospector
hmi
)
throws
Exception
{
SecurityFilterChain
configHttpSecurity
(
HttpSecurity
httpSecurity
,
HandlerMappingIntrospector
hmi
)
throws
Exception
{
httpSecurity
.
authorizeHttpRequests
(
auth
->
auth
.
anyRequest
().
permitAll
())
httpSecurity
.
authorizeHttpRequests
(
auth
->
auth
.
anyRequest
().
permitAll
())
.
csrf
().
disable
();
.
csrf
(
config
->
config
.
disable
())
.
cors
(
config
->
config
.
disable
());
return
httpSecurity
.
build
();
return
httpSecurity
.
build
();
}
}
...
...
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