Ho seguente controller:Primavera regolatore REST generico: analisi corpo della richiesta
@RestController
@RequestMapping(value = "/{entity}", produces = MediaType.APPLICATION_JSON_VALUE)
public class CrudController<T extends SomeSuperEntity> {
@RequestMapping(method = GET)
public Iterable<T> findAll(@PathVariable String entity) {
}
@RequestMapping(value = "{id}", method = GET)
public T findOne(@PathVariable String entity, @PathVariable String id) {
}
@RequestMapping(method = POST)
public void save(@PathVariable String entity, @RequestBody T body) {
}
}
SomeSuperEntity
classe assomiglia:
public abstract class SomeSuperEntity extends AbstractEntity {
// some logic
}
E AbstractEntity
sua classe astratta con qualche campo:
public abstract class AbstractEntity implements Comparable<AbstractEntity>, Serializable {
private Timestamp firstField;
private String secondField;
public Timestamp getFirstField() {
return firstField;
}
public void setFirstField(Timestamp firstField) {
this.firstField = firstField;
}
public String getSecondField() {
return secondField;
}
public void setSecondField(String secondField) {
this.secondField = secondField;
}
}
Tutte le sottoclassi di SomeSuperEntity
- JavaBeans semplici. In caso di metodi findAll()
e findOne(id)
, tutto funziona correttamente. Creo entità nel livello di servizio e ritorna al client come JSON con tutti i campi dichiarati in sottoclasse e in AbstractEntity
.
Ma quando ho cercato di ottenere richiesta corpo in save(entity, body)
, ho ottenuto l'errore seguente:
Could not read document: Can not construct instance of SomeSuperEntity, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information
se tolgo astratto da SomeSuperEntity
, tutto funziona, ma chiedo corpo ho ottenuto solo quei campi, che ha dichiarato in AbstractEntity
.
E qui è la mia domanda, c'è qualche soluzione per tali problemi nel mio caso? In caso contrario, quale sarebbe la soluzione migliore qui senza modifiche di struttura (la creazione di subcontloller per ciascuna entità non è un'opzione)? Recuperare il corpo come testo normale sarebbe una buona idea? O sarebbe meglio usare Map
per questo?
Sto utilizzando Spring v4.2.1 e Jackson 2.6.3 come convertitore.
C'è un po 'di informazioni sui controller generici, ma non sono riuscito a trovare nulla che riguardasse il mio caso. Quindi, per favore, naviga in caso di domande doppie.
Grazie in anticipo.
UPD: Attualmente il suo funzionamento come segue: aggiungo aggiungere ulteriore controllo nel mio MessageConverter
e definire @RequestBody
come String
Poi, il livello di servizio, definisco quanto entità ha ricevuto (in JSON pianura) e convertirlo:
final EntityMetaData entityMetadata = getEntityMetadataByName(alias);
final T parsedEntity = getGlobalGson().fromJson(entity, entityMetadata.getEntityType());
Dove EntityMetaData
è enum
con relazioni definite betw un alias entità e classe. Alias viene fornito come @PathVariable
.
Spring creerà un singolo oggetto per il tipo 'CrudController'. Non ci sono ulteriori informazioni sul tipo, es. il sottotipo 'SomeSuperEntity'. Dove ti aspetti che Spring (e poi Jackson) ottenga? –
Fondamentalmente, non fare quello che hai fatto con 'CrudController'. Crea una lezione '@ Controller' dedicata per ogni tipo che ti interessa, con mappature appropriate. –
È interessante. Perché? Cosa c'è di sbagliato nel fornire un endpoint generale '/ animals' o'/animals/1' per ottenere tutti gli animali o qualsiasi animale con 'ID = 1' indipendentemente dal fatto che si tratti di cane o gatto? Suggerisci di costringere le persone a sapere in anticipo se stanno richiedendo cani o gatti, giusto? Mi piace '/ animals/dogs/1'. Inoltre, se vuoi ottenere tutti gli animali devi iterare su tutti i sottotipi di animali che raccolgono insieme '/ animals/dogs','/animals/cats' ecc. Sto solo chiedendo come sto cercando di risolvere il caso di utilizzo simile io stesso e faticando a trovare il modo migliore. –