2015-01-29 17 views
12

Sto provando a leggere le intestazioni HTTP in REST API basata su Spring. Ho seguito this. Ma sto ricevendo questo errore:Lettura di intestazioni HTTP in un controller REST Spring

No message body reader has been found for class java.lang.String,
ContentType: application/octet-stream

Sono nuovo a Java e Spring quindi non riesco a capirlo.

Ecco come il mio invito si presenta come:

@WebService(serviceName = "common") 
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) 
public interface CommonApiService { 

    @GET 
    @Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
    @Produces(MediaType.APPLICATION_JSON) 
    @Path("/data") 
    public ResponseEntity<Data> getData(@RequestHeader(value="User-Agent") String userAgent, @DefaultValue ("") @QueryParam("ID") String id); 
} 

ho provato @Context: HTTPHeader è null in questo caso.

Come ottenere valori dalle intestazioni HTTP?

+0

La tua richiesta effettiva viene inviata come 'application/octect-stream' che Spring non può deserializzare su un tipo di dati String. Metti che sia 'application/json' (se hai Jackson sul classpath) o qualunque cosa ti aspetti di consumare e potresti essere in grado di andare da qualche parte. Stai per caso tentando di caricare un file sul tuo controller REST? – JamesENL

+0

Sto utilizzando Google Postman per effettuare la chiamata. Ho impostato il tipo di contenuto su application/json e ho ancora ricevuto l'errore. –

risposta

31

L'errore che si ottiene non sembra essere correlato alla RequestHeader.

E ti sembra di essere fonte di confusione servizi primavera riposo con JAX-RS, la firma metodo dovrebbe essere qualcosa del tipo:

@RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "data") 
@ResponseBody 
public ResponseEntity<Data> getData(@RequestHeader(value="User-Agent") String userAgent, @RequestParam(value = "ID", defaultValue = "") String id) { 
    // your code goes here 
} 

E la classe resto dovrebbe avere annotazioni come:

@Controller 
@RequestMapping("/rest/") 


Per quanto riguarda la vera domanda, un altro modo per ottenere le intestazioni HTTP è inserire il HttpServletRequest nel tuo metodo e quindi ottenere l'intestazione desiderata da lì.

Esempio:

@RequestMapping(produces = "application/json", method = RequestMethod.GET, value = "data") 
@ResponseBody 
public ResponseEntity<Data> getData(HttpServletRequest request, @RequestParam(value = "ID", defaultValue = "") String id) { 
    String userAgent = request.getHeader("user-agent"); 
} 

Non preoccuparti per l'iniezione del HttpServletRequest perché la primavera fa che la magia per voi;)

+0

Aggiornata la domanda. –

+0

Stai ancora mescolando i framework, stai cercando di usare jax-rs AND Spring rest. Look and mine e @JamesMassey rispondono per utilizzare l'api di riposo a molla. –

5

ho intenzione di darvi un esempio di come ho leggere le intestazioni REST per i miei controller. I miei controller accettano solo application/json come tipo di richiesta se ho dei dati che devono essere letti. Sospetto che il tuo problema sia che hai un'applicazione/octet-stream che Spring non sa come gestire.

Normalmente i miei controller simile a questa:

@Controller 
public class FooController { 
    @Autowired 
    private DataService dataService; 

    @RequestMapping(value="/foo/", method = RequestMethod.GET) 
    @ResponseBody 
    public ResponseEntity<Data> getData(@RequestHeader String dataId){ 
     return ResponseEntity.newInstance(dataService.getData(dataId); 
    } 

Ora c'è un sacco di codice fare cose in background qui quindi mi scomposizione per voi.

ResponseEntity è un oggetto personalizzato restituito da ogni controller. Contiene una fabbrica statica che consente la creazione di nuove istanze. Il mio servizio dati è una classe di servizio standard.

La magia accade dietro le quinte, perché stai lavorando con JSON, devi dire a Spring di usare Jackson per mappare gli oggetti HttpRequest in modo che sappia cosa hai a che fare.

A tale scopo, specificando questo all'interno del vostro <mvc:annotation-driven> blocco della vostra configurazione

<mvc:annotation-driven> 
    <mvc:message-converters> 
     <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> 
      <property name="objectMapper" ref="objectMapper" /> 
     </bean> 
    </mvc:message-converters> 
</mvc:annotation-driven> 

ObjectMapper è semplicemente un'estensione del com.fasterxml.jackson.databind.ObjectMapper ed è quello che utilizza Jackson per mappare in realtà la richiesta da JSON in un oggetto.

Ho il sospetto che tu stia ricevendo un'eccezione perché non hai specificato un mapper in grado di leggere un Octet-Stream in un oggetto o qualcosa che Spring può gestire. Se stai provando a fare un upload di file, è qualcosa di completamente diverso.

Quindi la mia richiesta che viene inviata al mio controller sembra qualcosa del genere, semplicemente ha un'intestazione extra chiamata dataId.

Se si voleva cambiare la situazione a un parametro di richiesta e utilizzare @RequestParam String dataId per leggere l'ID dalla richiesta richiesta sarebbe simile a questa:

contactId : {"fooId"} 

Questo parametro di richiesta può essere così complesso come ti piace . Puoi serializzare un intero oggetto in JSON, inviarlo come parametro di richiesta e Spring lo serializzerà (usando Jackson) in un oggetto Java pronto per l'uso.

Esempio In Controller:

@RequestMapping(value = "/penguin Details/", method = RequestMethod.GET) 
@ResponseBody 
public DataProcessingResponseDTO<Pengin> getPenguinDetailsFromList(
     @RequestParam DataProcessingRequestDTO jsonPenguinRequestDTO) 

Richiesta Sent:

jsonPengiunRequestDTO: { 
    "draw": 1, 
    "columns": [ 
     { 
      "data": { 
       "_": "toAddress", 
       "header": "toAddress" 
      }, 
      "name": "toAddress", 
      "searchable": true, 
      "orderable": true, 
      "search": { 
       "value": "", 
       "regex": false 
      } 
     }, 
     { 
      "data": { 
       "_": "fromAddress", 
       "header": "fromAddress" 
      }, 
      "name": "fromAddress", 
      "searchable": true, 
      "orderable": true, 
      "search": { 
       "value": "", 
       "regex": false 
      } 
     }, 
     { 
      "data": { 
       "_": "customerCampaignId", 
       "header": "customerCampaignId" 
      }, 
      "name": "customerCampaignId", 
      "searchable": true, 
      "orderable": true, 
      "search": { 
       "value": "", 
       "regex": false 
      } 
     }, 
     { 
      "data": { 
       "_": "penguinId", 
       "header": "penguinId" 
      }, 
      "name": "penguinId", 
      "searchable": false, 
      "orderable": true, 
      "search": { 
       "value": "", 
       "regex": false 
      } 
     }, 
     { 
      "data": { 
       "_": "validpenguin", 
       "header": "validpenguin" 
      }, 
      "name": "validpenguin", 
      "searchable": true, 
      "orderable": true, 
      "search": { 
       "value": "", 
       "regex": false 
      } 
     }, 
     { 
      "data": { 
       "_": "", 
       "header": "" 
      }, 
      "name": "", 
      "searchable": false, 
      "orderable": false, 
      "search": { 
       "value": "", 
       "regex": false 
      } 
     } 
    ], 
    "order": [ 
     { 
      "column": 0, 
      "dir": "asc" 
     } 
    ], 
    "start": 0, 
    "length": 10, 
    "search": { 
     "value": "", 
     "regex": false 
    }, 
    "objectId": "30" 
} 

che viene automaticamente serializzato di nuovo in un oggetto DataProcessingRequestDTO prima di essere dato al controller pronto per me da usare.

Come potete vedere, questo è abbastanza potente che consente di serializzare i dati da JSON a un oggetto senza dover scrivere una singola riga di codice. È possibile farlo per @RequestParam e @RequestBody che consente di accedere a JSON all'interno dei parametri o del corpo della richiesta rispettivamente.

Ora che si dispone di un esempio concreto di spegnimento, non si dovrebbe avere alcun problema una volta modificato il tipo di richiesta su application/json.

Problemi correlati