GetMapping e PathVariable

di il
12 risposte

GetMapping e PathVariable

Salve, dovrei usare per un progetto fatto con springboot, il getmapping per creare una rotta che, passato un id, mi restituisca tutte le classi che hanno lo stesso id(sto facendo dei test usando l'id, poi dovrei cercare prodotti usando altri parametri).

Come esempio ho questo progetto, vi allego i vari codici:
Questa è la classe usata per dei prodotti alimentari
package it.progetto.DemoSpringBootApp.model;

public class Product {
	private int id;
	private String name;	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}	
}
Questa è l'interfaccia che richiama le funzioni:
package it.progetto.DemoSpringBootApp.service;
import java.util.Collection;

import org.springframework.http.ResponseEntity;

import it.progetto.DemoSpringBootApp.model.Product;

public interface ProductService {
		public abstract void CreateProduct(Product product);
		public abstract Collection<Product>getProducts();		
}
Questa è la classe che implementa quella precedente:
package it.progetto.DemoSpringBootApp.service;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;

import it.progetto.DemoSpringBootApp.model.Product;

@Service
public class ProductServiceImpl implements ProductService {
	private static Map<Integer, Product>ProductRepo=new HashMap<>();
	public ProductServiceImpl() {
		Product miele=new Product();
		miele.setId(1);
		miele.setName("Miele");
		ProductRepo.put(miele.getId(),miele);
	
		Product acqua=new Product();
		acqua.setId(2);
		acqua.setName("Acqua");
		ProductRepo.put(acqua.getId(),acqua);		
	}
		
	@Override
	public void CreateProduct(Product product) {
		if(ProductRepo.containsKey(product.getId())) {
			throw new ResponseStatusException(HttpStatus.BAD_REQUEST,"Existing id...");
		}
		ProductRepo.put(product.getId(), product);	
	}
	@Override
	public Collection<Product> getProducts() {		
		return ProductRepo.values();
	}	
}

Infine ecco il controller, dove ho fatto solo una rotta che mi restituisce l'intera lista di prodotti:
package it.progetto.DemoSpringBootApp.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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 it.progetto.DemoSpringBootApp.service.ProductService;

@RestController
public class ProductController {
	@Autowired
	ProductService productService;
	
	@RequestMapping(value="/products")
	public ResponseEntity<Object>getProduct(){
		return new ResponseEntity<>(productService.getProducts(), HttpStatus.OK);
	}
Vi chiedevo quindi se potreste aiutarmi a creare una rotta per filtrare i risultati, in base a dei parametri passati(Nel mio caso, per esempio l'id).
Vi ringrazio

12 Risposte

  • Re: GetMapping e PathVariable

    LeoTheGamer ha scritto:


    @RestController
    public class ProductController {
    	@Autowired
    	ProductService productService;
    	
    	@RequestMapping(value="/products")
    	public ResponseEntity<Object>getProduct(){
    		return new ResponseEntity<>(productService.getProducts(), HttpStatus.OK);
    	}
    Innanzitutto

    @GetMapping("/xyz")

    è esattamente l'equivalente di

    @RequestMapping(value = "/xyz", method = RequestMethod.GET)

    E dato che il productService.getProducts() fornisce un Collection<Product>, allora sarebbe più appropriato mettere ResponseEntity<Collection<Product>>.

    LeoTheGamer ha scritto:


    Vi chiedevo quindi se potreste aiutarmi a creare una rotta per filtrare i risultati, in base a dei parametri passati(Nel mio caso, per esempio l'id).
    Basta iniziare con es.:
        @GetMapping("/products/{id}")
        public ResponseEntity<Product> getProductById(@PathVariable("id") Integer id) {
            // chiama sul service es. un getProductById(id)
            // ritorno del product ...
        }

    P.S. non so se il HashMap nel service è temporaneo e/o per prova. Ma qui sei in un contesto multi-thread e ... HashMap NON è thread-safe.
  • Re: GetMapping e PathVariable

    Ciao, ho scritto questo in service:
    public abstract Collection<Product> getProductById(int id);
    Questo nell implementazione di service:
    @Override
    	public Collection<Product> getProductById(int id) {
    		
    		 return (Collection<Product>) ProductRepo.get(id);
    	}
    infine questo nel controller:
    @GetMapping("/products/{id}")
        public ResponseEntity<Product> getProductById(@PathVariable("id") Integer id) {
    	return new ResponseEntity<>(productService.getProductById(id));
    	
    }
    ma Mi da errore nel controller dicendo: Cannot infer type arguments for ResponseEntity<>

    Dove avrei sbagliato? Nell'implementazione di service scrivendo male il return?
    Grazie
  • Re: GetMapping e PathVariable

    LeoTheGamer ha scritto:


    public abstract Collection<Product> getProductById(int id);
    Se il id è la "chiave univoca", ci si aspetta al massimo 1 oggetto, non una collection.

    LeoTheGamer ha scritto:


    @Override
    	public Collection<Product> getProductById(int id) {
    		
    		 return (Collection<Product>) ProductRepo.get(id);
    	}
    E' comunque sbagliato, il get() dà 1 oggetto Product, non un Collection.

    LeoTheGamer ha scritto:


    ma Mi da errore nel controller dicendo: Cannot infer type arguments for ResponseEntity<>
    Comunque, stessa questione di prima.
  • Re: GetMapping e PathVariable

    E come farei allora per avere la collection di elementi che contengono quel dato che gli passerei con la rotta?
  • Re: GetMapping e PathVariable

    LeoTheGamer ha scritto:


    E come farei allora per avere la collection di elementi che contengono quel dato che gli passerei con la rotta?
    Allora, se tieni una mappa così:

    private Map<Integer, Product> productRepo = new HashMap<>();

    è assolutamente ok, perché stai "indicizzando" gli oggetti per un id che è "univoco". Quindi a fronte di 1 id, otterrai 1 Product (la vedi la parametrizzazione, è Product, non Collection<Product> ). A livello di API web, quindi è corretto avere un endpoint che richiede 1 id e fornisce 1 Product.

    @GetMapping("/products/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable("id") Integer id) {

    Ora: hai bisogno di "indicizzare" anche per altri dati che NON sono "univoci"? Tipo ad esempio un code String non univoco? Allora potresti aggiungere un'altra mappa:

    private Map<Integer, Product> productRepoById = new HashMap<>();
    private Map<String, List<Product>> productRepoByCode = new HashMap<>();

    Il punto/problema è che gestire più mappe così è decisamente più difficile, perché tutte le operazioni (aggiunta, eliminazione ecc...) vanno fatte tutte in modo corretto/coerente. E quindi ora c'è un'altra domanda: stai facendo tutto questo con le mappe per quale motivo? Per studio/prova/test? Allora può essere ok.
  • Re: GetMapping e PathVariable

    Per testing, e l'unica operazione che dovrei fare è la ricerca. Grazie mille comunque
  • Re: GetMapping e PathVariable

    LeoTheGamer ha scritto:


    Per testing, e l'unica operazione che dovrei fare è la ricerca. Grazie mille comunque
    Giusto per capire: cosa intendi per "testing"? Nel senso che stai usando quella map per motivi tuoi di "studio" non potendo e/o volendo usare un DBMS reale?
  • Re: GetMapping e PathVariable

    Si esatto
  • Re: GetMapping e PathVariable

    LeoTheGamer ha scritto:


    Si esatto
    Allora l'uso di collezioni in memoria può andare bene, se appunto per scopi di prove/esercizio/studio senza DB reale.

    In tal caso potresti tenere una banale lista dei prodotti ed eventualmente affiancarci una map per "indicizzare" sul id.
    private List<Product> productRepo = new ArrayList<>();
    private Map<Integer, Product> productRepoById = new HashMap<>();
    Chiaramente sono da gestire ed aggiornare in maniera coerente. Aggiungere altre "indicizzazioni" per attributi non "univoci" risulta più scomodo/difficile da gestire (ma non impossibile).

    Riguardo la API web, se vuoi seguire strettamente i principi REST, allora dovrebbe risultare così:

    GET blabla/products
    per ottenere una lista di prodotti. La lista potrebbe essere filtrata e/o "paginata" usando appositi parametri, es.

    GET blabla/products?name=xyz

    poi

    GET blabla/products/NNNN
    per ottenere il dettaglio di un singolo product di id NNNN

    POST blabla/products
    per inserire un product (dal request body)

    PUT blabla/products/NNNN
    per aggiornare un product di id NNNN (dal request body)

    DELETE blabla/products/NNNN
    per eliminare un product di id NNNN

    Questo per quanto riguarda gli url, per gli status code da inviare in response ci sono delle convenzioni tipiche.
  • Re: GetMapping e PathVariable

    Ok ho capito grazie mille. Invece se dovessi avere a che fare con DB reali, a quel punto non mi converebbe più usare le hasmap giusto? In quel caso come li gestisco? A grandi linee giusto per parlare
  • Re: GetMapping e PathVariable

    LeoTheGamer ha scritto:


    Invece se dovessi avere a che fare con DB reali, a quel punto non mi converebbe più usare le hasmap giusto?
    Sì, infatti map, list ecc.. non servono più come "store" dei dati.

    LeoTheGamer ha scritto:


    In quel caso come li gestisco? A grandi linee giusto per parlare
    Per usare un DBMS reale devi usare delle API apposite. E qui si aprono svariate possibilità, in particolare essendo su Spring.
    Puoi usare JDBC "puro" (sconsigliato però in ambito Spring). Puoi usare il JdbcTemplate di Spring. Oppure puoi usare un ORM (es. Hibernate) tramite JPA "puro" oppure tramite Spring Data JPA.
    EDIT: e altre librerie tipo MyBatis.
  • Re: GetMapping e PathVariable

    Ok ora inizio a capire meglio, comunque come sempre ti ringrazio, disponibile come sempre andbin!
Devi accedere o registrarti per scrivere nel forum
12 risposte