Utilizzo di Spring RestTemplate Interceptor

1. Panoramica

In questo tutorial, impareremo come implementare uno Spring RestTemplateInterceptor.

Esamineremo un esempio in cui creeremo un intercettore che aggiunge un'intestazione personalizzata alla risposta.

2. Scenari di utilizzo degli intercettatori

Oltre alla modifica dell'intestazione, alcuni degli altri casi d'uso in cui è utile un intercettore RestTemplate sono:

  • Registrazione di richieste e risposte
  • Riprovare le richieste con una strategia di backoff configurabile
  • Richiesta di rifiuto in base a determinati parametri di richiesta
  • Modifica dell'indirizzo URL della richiesta

3. Creazione dell'Interceptor

Nella maggior parte dei paradigmi di programmazione, gli intercettori sono una parte essenziale che consente ai programmatori di controllare l'esecuzione intercettandola. Il framework Spring supporta anche una varietà di intercettori per scopi diversi.

Spring RestTemplate ci consente di aggiungere intercettori che implementano l' interfaccia ClientHttpRequestInterceptor . Il metodo di intercettazione (HttpRequest, byte [], ClientHttpRequestExecution) di questa interfaccia intercetterà la richiesta fornita e restituirà la risposta dandoci accesso alla richiesta , al corpo e agli oggetti di esecuzione .

Useremo l' argomento ClientHttpRequestExecution per eseguire l'effettiva esecuzione e passare la richiesta alla successiva catena di processi.

Come primo passo, creiamo una classe interceptor che implementa l' interfaccia ClientHttpRequestInterceptor :

public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor { @Override public ClientHttpResponse intercept( HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { ClientHttpResponse response = execution.execute(request, body); response.getHeaders().add("Foo", "bar"); return response; } }

Il nostro intercettore verrà richiamato per ogni richiesta in arrivo e aggiungerà un'intestazione personalizzata Foo a ogni risposta, una volta completata e restituita l'esecuzione.

Poiché il metodo intercept () includeva la richiesta e il corpo come argomenti, è anche possibile apportare qualsiasi modifica alla richiesta o persino negare l'esecuzione della richiesta in base a determinate condizioni.

4. Configurazione di RestTemplate

Ora che abbiamo creato il nostro interceptor, creiamo il bean RestTemplate e aggiungiamo il nostro interceptor ad esso:

@Configuration public class RestClientConfig { @Bean public RestTemplate restTemplate() { RestTemplate restTemplate = new RestTemplate(); List interceptors = restTemplate.getInterceptors(); if (CollectionUtils.isEmpty(interceptors)) { interceptors = new ArrayList(); } interceptors.add(new RestTemplateHeaderModifierInterceptor()); restTemplate.setInterceptors(interceptors); return restTemplate; } }

In alcuni casi, potrebbero esserci degli intercettori già aggiunti all'oggetto RestTemplate . Quindi, per assicurarsi che tutto funzioni come previsto, il nostro codice inizializzerà l'elenco degli intercettatori solo se è vuoto.

Come mostra il nostro codice, stiamo usando il costruttore predefinito per creare l' oggetto RestTemplate , ma ci sono alcuni scenari in cui dobbiamo leggere il flusso di richiesta / risposta due volte.

Ad esempio, se vogliamo che il nostro intercettore funzioni come un logger di richieste / risposte, allora dobbiamo leggerlo due volte: la prima volta dall'interceptor e la seconda dal client.

L'implementazione predefinita ci consente di leggere il flusso di risposta solo una volta. Per soddisfare tali scenari specifici, Spring fornisce una classe speciale chiamata BufferingClientHttpRequestFactory. Come suggerisce il nome, questa classe bufferizzerà la richiesta / risposta nella memoria JVM per un utilizzo multiplo.

Ecco come viene inizializzato l' oggetto RestTemplate utilizzando BufferingClientHttpRequestFactory per abilitare la memorizzazione nella cache del flusso di richiesta / risposta:

RestTemplate restTemplate = new RestTemplate( new BufferingClientHttpRequestFactory( new SimpleClientHttpRequestFactory() ) );

5. Testare il nostro esempio

Ecco il test case di JUnit per testare il nostro intercettore RestTemplate :

public class RestTemplateItegrationTest { @Autowired RestTemplate restTemplate; @Test public void givenRestTemplate_whenRequested_thenLogAndModifyResponse() { LoginForm loginForm = new LoginForm("username", "password"); HttpEntity requestEntity = new HttpEntity(loginForm); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); ResponseEntity responseEntity = restTemplate.postForEntity( "//httpbin.org/post", requestEntity, String.class ); assertThat( responseEntity.getStatusCode(), is(equalTo(HttpStatus.OK)) ); assertThat( responseEntity.getHeaders().get("Foo").get(0), is(equalTo("bar")) ); } }

Qui abbiamo utilizzato il servizio di richiesta e risposta HTTP ospitato gratuitamente //httpbin.orgper pubblicare i nostri dati. Questo servizio di test restituirà il nostro corpo della richiesta insieme ad alcuni metadati.

6. Conclusione

Questo tutorial è tutto su come impostare un intercettore e aggiungerlo all'oggetto RestTemplate . Questo tipo di intercettatori può essere utilizzato anche per filtrare, monitorare e controllare le richieste in arrivo.

Un caso d'uso comune per un intercettore RestTemplate è la modifica dell'intestazione, che abbiamo illustrato in dettaglio in questo articolo.

E, come sempre, puoi trovare il codice di esempio sul progetto Github. Questo è un progetto basato su Maven, quindi dovrebbe essere facile da importare ed eseguire così com'è.