Simple Spring HTTP Remoting Esempio

Sto usando questo post di blog per dimostrare con un semplice esempio l'uso di HTTP Remoting di Spring Framework. Ci sono numerose risorse online su questo argomento, quindi la mia intenzione qui è quella di fornire una dimostrazione estremamente semplice ma completa dell'utilizzo di HTTP Remoting di Spring con client non browser.

L'approccio Spring a HTTP Remoting consente ai client di comunicare con il codice del server ospitato da Spring tramite HTTP senza che il codice client richieda alcuna conoscenza dell'utilizzo di HTTP. Al contrario, il codice Java del client "vede" solo i normali oggetti Java correlati al business (di solito le interfacce) anziché gli oggetti specifici di HTTP.

Spring HTTP Remoting generalmente richiede Spring e Java sia sul lato server che sul lato client. Tuttavia, se questi due requisiti possono essere soddisfatti, Spring HTTP Remoting è facilmente applicabile.

I passaggi seguenti consentono la comunicazione HTTP tra client e server ospitati da Spring. Dopo aver delineato brevemente i passaggi, li approfondirò in modo più dettagliato (inclusi esempi di codice).

  1. Creare o utilizzare un bean Spring esistente che in genere implementa un'interfaccia Java.

    Questo non è niente di speciale per il remoting HTTP ed è lo stesso passaggio che dovresti fare per fare la maggior parte delle cose in primavera (una notevole eccezione è

    Spring JDBC

    che non richiede l'utilizzo di fagioli primaverili).

  2. Creare il file di configurazione XML Spring per associare il bean creato nel passaggio 1 con un contesto dell'applicazione Spring.

    Come per il passaggio # 1, questo file XML non è niente di particolare per Spring HTTP Remoting, ma è invece comune a quasi tutti i collegamenti e le configurazioni di Spring Framework.

  3. Crea o aggiungi al web.xmlfile.

    Questo terzo passaggio è il primo passaggio più specifico per Spring HTTP Remoting, ma è ancora generalmente applicabile con

    Framework Spring MVC

    . Questo passaggio include l'aggiunta della classe servlet e delle mappature URL come normalmente si usa con

    Java EE

    servlet

    e

    JavaServer Pages

    . La parte più importante di questo passaggio è specificare la primavera

    DispatcherServlet

    . In questo viene fornito anche un "collegamento" opzionale

    web.xml

    in un percorso di configurazione del contesto in cui si trovano e utilizzati uno o più file di contesto dell'applicazione Spring XML.

  4. Creare il file di contesto servlet specifico per Spring.

    Questo file XML assomiglia molto a un "normale" file di configurazione XML del contesto dell'applicazione Spring, ma il suo nome è prescritto dalla convenzione del nome del servlet seguito da un trattino e dalla parola servlet. In altre parole, se il servlet è stato chiamato "qualcosa" nel file

    web.xml

    file, questo file di configurazione servlet Spring verrebbe chiamato

    somewebthing-servlet.xml

    . Questo file contiene la configurazione per

    HttpInvokerServiceExporter

    (la parte di ciò che è particolare per il servizio remoto HTTP trattato in questo articolo di blog) e le informazioni sulla mappatura degli URL.

  5. Test!

    Sebbene il semplice client scriverà senza HTTP in mente e sembrerà che utilizzi solo oggetti Java, in realtà richiamerà il servizio tramite HTTP. Ciò sarà "dimostrato" eseguendo il client senza il servizio distribuito e controllando il codice di errore HTTP risultante.

Passerò ora alla dimostrazione dei passaggi precedenti in maggiore dettaglio e cercherò di illustrarli concretamente con esempi di codice.

Passaggio 1: il fagiolo e la sua interfaccia

Questo passaggio non è diverso dalla definizione delle classi e delle interfacce Java che implementano per l'uso con Spring. I seguenti elenchi di codice mostrano l'interfaccia ( StateCapitalServiceIF) e la classe di implementazione ( StateCapitalService) utilizzata per questo esempio.

--- StateCapitalServiceIF.java ---

package examples.springhttp; import java.io.Serializable; /** * The State Capital Service interface that the client will use to access * server-side functionality via HTTP. */ public interface StateCapitalServiceIF extends Serializable { /** * Provide capital of state whose name is provided. * * @param stateName Name of state whose capital is desired. * @return Capital of the specified state; null if not found. */ public String getCapital(final String stateName); } 

--- StateCapitalService.java ---

package examples.springhttp; import java.util.Map; /** * Implementation of functionality to be run after being called by client via * HTTP. */ public class StateCapitalService implements StateCapitalServiceIF { Map statesAndCapitals = null; public StateCapitalService() { } /** * Set my states to state capitals mapping. * * @param statesAndCapitals States to state capitals mapping. */ public void setStatesAndCapitals(final Map statesAndCapitals) { this.statesAndCapitals = statesAndCapitals; } /** * Provide capital of state whose name is provided. * * @param stateName Name of state whose capital is desired. * @return Capital of the specified state; null if not found. */ public String getCapital(final String stateName) { return this.statesAndCapitals.get(stateName); } } 

Passaggio 2: file di configurazione del contesto dell'applicazione Spring

Mi piace mantenere la configurazione specifica per HTTP di Spring separata dalla configurazione XML del bean. Pertanto, la configurazione del bean è esattamente come si vedrebbe normalmente con Spring. Per configurare la StateCapitalServiceclasse precedente, viene utilizzata la seguente configurazione:

--- spring-http-config.xml ---


    

Finora, non è stato fatto nulla di specifico per HTTP Remoting. Infatti, il bean, la sua interfaccia e la sua configurazione del contesto dell'applicazione XML potrebbero essere tutti eseguiti da una normale classe Java SE come quella mostrata di seguito:

--- MainServiceAppContext.java ---

package examples.springhttp; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Demonstrates how Spring bean can be used without any HTTP involvement. */ public class MainServiceAppContext { public static void printStateInfo( final StateCapitalServiceIF stateCapitalMapper, final String state) { System.out.println( "The capital of " + state + " is " + stateCapitalMapper.getCapital(state)); } /** * @param args the command line arguments */ public static void main(String[] args) { final ApplicationContext context = new ClassPathXmlApplicationContext( "examples/springhttp/spring-http-config.xml" ); StateCapitalServiceIF stateCapitalMapper = (StateCapitalServiceIF) context.getBean("stateCapitalService"); printStateInfo(stateCapitalMapper, "Alabama"); printStateInfo(stateCapitalMapper, "Colorado"); } } 

Passaggio 3: il web.xmlfile

Questo web.xmlfile è familiare a chiunque abbia sviluppato un'applicazione Web Java EE. L' web.xmlusato in questo esempio è mostrato di seguito.


    
      Simple Spring HTTP Remoting Example This is meant as an extremely simple example of using Spring's HTTP Remoting capability. statesCapitals org.springframework.web.servlet.DispatcherServlet 1 statesCapitals /statesCapitals org.springframework.web.context.ContextLoaderListener contextConfigLocation /WEB-INF/examples/springhttp/spring-http-config.xml 
    

Passaggio 4: il file di configurazione del contesto del servlet

Poiché il servlet in questo esempio è denominato "statesCapitals", è necessario fornire un file di configurazione del servlet Spring denominato statesCapitals-servlet.xml. Viene mostrato di seguito:

--- statesCapitals-servlet.xml ---


    
      examples.springhttp.StateCapitalServiceIF httpStateCapitalService 
    

Passaggio 5: testarlo

Dobbiamo configurare il client per comunicare tramite HTTP con la nostra applicazione lato server. La configurazione per questo è contenuta in spring-http-client-config.xmlquesto esempio ed è mostrata di seguito:

--- spring-http-client-config.xml ---


    
      //localhost:8080/SpringHTTPExample/statesCapitals examples.springhttp.StateCapitalServiceIF 
    

Il codice client che utilizza l'XML di cui sopra per avviare un contenitore Spring e chiamare il codice lato server tramite HTTP è nella classe HttpCliente tale codice viene mostrato di seguito:

--- HttpClient.java ---

package examples.springhttp.client; import examples.springhttp.StateCapitalServiceIF; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * This class demonstrates a client of a Spring HTTP-exposed service and shows * how the client interacts with the server as if using normal Java objects * rather than using anything HTTP specific. */ public class HttpClient { public static void printStateInfo( final StateCapitalServiceIF stateCapitalMapper, final String state) { System.out.println( "The capital of " + state + " is " + stateCapitalMapper.getCapital(state)); } public static void main(final String[] arguments) { final ApplicationContext context = new ClassPathXmlApplicationContext( "examples/springhttp/client/spring-http-client-config.xml"); final StateCapitalServiceIF stateCapitalService = (StateCapitalServiceIF) context.getBean("stateCapitalProxyService"); printStateInfo(stateCapitalService, "Colorado"); printStateInfo(stateCapitalService, "Alabama"); } }