Costruisci un'applicazione di chat in tempo reale con modulo e avvio a molla

In questo tutorial, utilizzeremo Spring Boot per l'ambiente di sviluppo Web, Websockets per la comunicazione in tempo reale, Tomcat per il contenitore di applicazioni Java, Gradle per la creazione e la gestione delle dipendenze, Thymeleaf per il rendering dei modelli, MongoDBper l'archiviazione dei dati e infine non ci sarà XML per le configurazioni dei bean. Solo per farti ispirato, alla fine di questo articolo, vedrai un'applicazione completamente funzionante come quella mostrata sotto.

1. Scenario

  1. Doe apre la pagina della chat per comunicare con i suoi amici.
  2. Viene richiesto di scegliere un soprannome.
  3. Entra nella pagina di chat e invia un messaggio. Il messaggio viene inviato all'endpoint Spring MVC per essere salvato nel database e trasmesso.
  4. L'endpoint specificato gestisce il messaggio e trasmette tale messaggio a tutti i client connessi al sistema di chat.

2. Costruire dipendenze e configurazione Gradle

Prima di procedere con la struttura interna del progetto, permettimi di spiegare quali librerie utilizzeremo per le funzionalità del progetto elencate sopra e gestirle utilizzando Gradle. Quando cloni il progetto da GitHub, vedrai un file chiamato build.gradle nella directory root del progetto come sotto.

buildscript repositories mavenCentral () dependencies classpath ("org.springframework.boot: spring-boot-gradle-plugin: 1.2.4.RELEASE") applica plugin: 'java' applica il plugin: 'eclipse' applica il plugin : plugin 'idea' apply: 'spring-boot' applica il plugin: 'war' jar baseName = 'realtime-chat' version = '0.1.0' war baseName = 'ROOT' sourceCompatibility = 1.7 targetCompatibility = 1.7 repository mavenCentral () sourceCompatibility = 1.7 targetCompatibility = 1.7 dipendenze providedRuntime 'org.springframework.boot: spring-boot-starter-tomcat' compile ("org.springframework.boot: spring-boot-starter-web") compilare (" org.springframework.boot: spring-boot-starter-thymeleaf ") compilare (" org.springframework.boot: spring-boot-starter-data-mongodb ") compilare (" org.springframework.boot: spring-boot-starter- websocket ") compile (" org.springframework: spring-messaging ") testCompile (" junit: junit ") task wrapper (tipo: Wrapper) gradleVersion = '2.3'

Non mi tufferò negli interni di Gradle, ma mi permetta di spiegare le parti di cui abbiamo bisogno per il nostro progetto. Spring Boot è costruito principalmente per lo sviluppo di applicazioni standalone in vaso formato. Nel nostro progetto, genereremo un guerra progetto invece di vaso. Questo perché Modulus ha bisogno di un file di guerra per distribuire automaticamente il progetto nel suo cloud. 

Per generare un file di guerra, abbiamo usato applica plugin: 'war'. Modulus si aspetta anche che il nome della guerra sia ROOT.war di default, ed è per questo che abbiamo usato:

war baseNome: 'ROOT.war'

Quando esegui il Gradle costruire attività, genererà un file di guerra da distribuire nel contenitore Tomcat. E infine, come puoi intuire, la sezione delle dipendenze è per le librerie di terze parti per azioni specifiche. 

Questo è tutto per la sezione delle dipendenze del progetto e puoi fare riferimento alla guida utente di Gradle per ulteriori informazioni su Gradle.

3. Progettazione software

Se si desidera sviluppare una buona applicazione, è consigliabile definire la struttura del progetto in piccoli pezzi. Puoi vedere i pezzi dell'intera architettura della nostra applicazione.

3.1. Modello

Stiamo sviluppando un'applicazione di chat, quindi possiamo dire che abbiamo un ChatMessageModel modello (cioè oggetto dominio). Mentre stiamo salvando o visualizzando i dettagli del messaggio chat, possiamo lanciare l'oggetto chat da o su questo ChatMessageModel modello. Inoltre, possiamo usare il Utente modello per gli utenti di chat, ma per rendere l'applicazione più semplice, useremo solo soprannome come testo Il ChatMessageModel il modello ha i seguenti campi: testo, autore, e CreateDate. La rappresentazione di classe di questo modello è la seguente:

pacchetto realtime.domain; import org.springframework.data.annotation.Id; import java.util.Date; / ** * @author huseyinbabal * / public class ChatMessageModel @Id ID stringa privata; testo String privato; autore privato di stringhe; Data privata createDate; public ChatMessageModel ()  public ChatMessageModel (String text, String author, Date createDate) this.text = text; this.author = autore; this.createDate = createDate;  public String getText () return text;  public void setText (String text) this.text = text;  public String getAuthor () return author;  public void setAuthor (String author) this.author = author;  public Date getCreateDate () return createDate;  public void setCreateDate (Date createDate) this.createDate = createDate;  @Override public String toString () return "" + "\" id \ ": \" "+ id + '\"' + ", \" text \ ": \" "+ text + '\"' + ", \" author \ ": \" "+ author + '\"' + ", \" createDate \ ": \" "+ createDate +" \ "" + '';  

Questo oggetto dominio ci aiuta a rappresentare il messaggio chat come JSON quando necessario. Il nostro modello è OK, quindi continuiamo con i controller.

3.2. controllore

Il controller è il comportamento della tua applicazione. Ciò significa che è necessario mantenere il controller semplice e in grado di interagire facilmente con i modelli di dominio e altri servizi. Ci aspettiamo che i nostri controllori gestiscano:

  1. Richieste di salvataggio messaggi chat
  2. Elenco degli ultimi messaggi di chat
  3. Servire la pagina dell'applicazione di chat
  4. Servire la pagina di accesso
  5. Trasmissione di messaggi di chat ai client

Qui puoi vedere gli endpoint generali:

pacchetto realtime.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import realtime.domain.ChatMessageModel; import realtime.message.ChatMessage; import realtime.repository.ChatMessageRepository; import java.util.Date; import java.util.List; / ** * @author huseyinbabal * / @Controller public class ChatMessageController @Autowired private ChatMessageRepository chatMessageRepository; @RequestMapping ("/ login") public String login () return "login";  @RequestMapping ("/ chat") public String chat () return "chat";  @RequestMapping (value = "/ messages", method = RequestMethod.POST) @MessageMapping ("/ newMessage") @SendTo ("/ topic / newMessage") public ChatMessage save (ChatMessageModel chatMessageModel) ChatMessageModel chatMessage = new ChatMessageModel (chatMessageModel .getText (), chatMessageModel.getAuthor (), new Date ()); ChatMessageModel message = chatMessageRepository.save (chatMessage); Elenco chatMessageModelList = chatMessageRepository.findAll (new PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent (); restituisce nuovo ChatMessage (chatMessageModelList.toString ());  @RequestMapping (value = "/ messages", method = RequestMethod.GET) public HttpEntity list () List chatMessageModelList = chatMessageRepository.findAll (new PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent (); restituire nuovo ResponseEntity (chatMessageModelList, HttpStatus.OK);  

Il primo e il secondo endpoint servono solo per il login e la pagina principale della chat. La terza azione riguarda la gestione della memorizzazione e della trasmissione di nuovi messaggi di chat. Dopo che il messaggio è stato memorizzato, verrà notificato ai client attraverso il / Topic / messaggiocanale. Per memorizzare i dati dei messaggi su MongoDB, useremo un repository MongoDB.  

Come puoi vedere, ci sono due tipi di endpoint / messaggi: GET e POST. Quando si effettua una richiesta POST all'endpoint / messaggi con il payload del messaggio corretto, verrà automaticamente trasmesso alla classe ChatMessageModel e il messaggio verrà salvato in MongoDB. Dopo aver salvato con successo, verrà automaticamente inviato ai client. Ma come? In quella azione, c'è un'annotazione @SendTo ( "/ argomento / newMessage"). Ciò invierà il contenuto restituito dalla funzione ai client. E il contenuto restituito è come di seguito:

... restituisce nuovo ChatMessage (chatMessageModelList.toString ()); ... 

Questo è l'ultimo messaggio dal database:

Il messaggio precedente verrà convertito in un formato per la comunicazione WebSocket. Questo messaggio di canale verrà gestito sul lato client con una libreria JavaScript di terze parti e verrà gestito nelle seguenti sezioni. 

Per le operazioni di messaggio db, primavera-boot-starter-data-mongodb viene usato. Questa libreria ci aiuta per le operazioni di repository e creare un oggetto repository per MongoDB è molto semplice. Puoi vedere l'esempio ChatMessageRepository sotto:

pacchetto realtime.repository; import org.springframework.data.mongodb.repository.MongoRepository; import realtime.domain.ChatMessageModel; import java.util.List; / ** * @author huseyinbabal * / interfaccia pubblica ChatMessageRepository estende MongoRepository  Elenco findAllByOrderByCreateDateAsc ();  

Se crei un'interfaccia ed estendi MongoRepository, sarai in grado di utilizzare automaticamente le operazioni CRUD come trova(), trova tutto(), salvare(), eccetera. 

Come potete vedere, MongoRepository si aspetta un oggetto dominio. Abbiamo già definito questo modello nella sezione Modello del tutorial. In questo repository, abbiamo definito una funzione personalizzata chiamata findAllByOrderByCreateDateAsc ()

Se hai mai usato l'JPA, puoi facilmente capirlo, ma lascia che ti spieghi brevemente. Se si definisce un nome di funzione in un'interfaccia che si estende MongoRepository, questo nome di funzione verrà analizzato automaticamente da una query sul back-end di Spring. Sarà qualcosa come:

SELECT * FROM ChatMessageModel WHERE 1 ORDINE BY createDate ASC

Nel ChatMessageController, abbiamo usato questa funzione e abbiamo anche usato le funzioni predefinite di MongoRepository:

chatMessageRepository.findAll (new PageRequest (0, 5, Sort.Direction.DESC, "createDate")). getContent ()

trova tutto viene utilizzato un parametro per l'ordinamento e l'impaginazione. Puoi dare un'occhiata alla guida sul sito web di Spring per maggiori dettagli su Spring JPA.

3.3. vista

Nella parte vista, abbiamo solo due pagine. Una di queste è la pagina di accesso, per ottenere il soprannome dell'utente, e la seconda è la pagina principale della chat per inviare messaggi agli utenti della chat. 

Come puoi vedere nella precedente sezione del controller, vengono renderizzati utilizzando due endpoint, /accessoe /ChiacchierarePer creare pagine interattive, utilizzeremo alcune librerie JavaScript di terze parti. Li useremo dalle pagine CDN. Puoi vedere la pagina di accesso qui sotto:

             

Scegli un nickname per accedere alla chat

Nella pagina di accesso, abbiamo una casella di testo di soprannome campione. Quando si fa clic Entra nella chat, il tuo nickname verrà salvato in un cookie. Questo nickname verrà utilizzato per impostare il campo dell'autore del messaggio di chat. Quando si fa clic Entra nella chat, la pagina di chat verrà aperta. Se hai già effettuato l'accesso e vai alla pagina di accesso, verrai reindirizzato alla pagina della chat. 

Ecco la pagina della chat:

                 

Applicazione di chat in tempo reale con Spring Boot, Websockets e MongoDB



Storia della chat

Questa pagina è per la semplice visualizzazione e l'invio di messaggi. I messaggi vengono consegnati a questa pagina tramite WebSockets. In questa pagina puoi vedere sockjs e stompjs. Questi sono per la gestione delle notifiche. Ogni volta che arriva un nuovo messaggio, l'area dei messaggi più recenti viene ripopolata. 

A proposito, quando apri per la prima volta la pagina della chat, gli ultimi messaggi verranno recuperati nell'area dei messaggi. Come puoi vedere dal lato JavaScript, il nostro canale messaggi è nuovo messaggio. Quindi, stiamo ascoltando questo canale e quando fai clic su Inviare pulsante, il messaggio nella casella di testo verrà inviato all'endpoint e tale messaggio verrà trasmesso ai client connessi dopo l'archiviazione riuscita.

Come puoi vedere, l'architettura del software qui è molto semplice e facile da sviluppare. Abbiamo un codice pronto per la produzione e lo distribuiamo su Modulus.

Modulus è uno dei migliori PaaS per la distribuzione, il ridimensionamento e il monitoraggio dell'applicazione nella lingua prescelta.

4. Distribuzione 

4.1. Prerequisiti

Prima di distribuire l'applicazione, creiamo un database usando il pannello di amministrazione Modulus. Hai bisogno di un account Modulus per la creazione di dba e l'implementazione dell'applicazione, quindi crea un account se non ne hai uno. 

Vai al dashboard Modulus e crea un database:

Nella schermata di creazione del database si prega di fornire un nome di database, selezionare la versione MongoDB (ho usato 2.6.3, quindi sarà meglio se si sceglie anche 2.6.3), e infine definire un utente per applicare le operazioni di lettura / scrittura del database. 

È possibile ottenere un URL MongoDB dopo aver creato correttamente il database. Useremo l'URL MongoDB nelle variabili d'ambiente che saranno usate dall'applicazione Spring Boot.

Per impostare le variabili di ambiente per MongoDB, è necessario disporre di un'applicazione. Vai a Cruscotto e fare clic progetti. In questa pagina, clicca Crea un nuovo progetto.

Per continuare con la configurazione delle variabili di ambiente, andare a Cruscotto e fare clic progetti. Seleziona il tuo progetto e clicca Amministrazione. Scorri verso il basso la pagina e imposta le variabili di ambiente con il tasto SPRING_DATA_MONGODB_URI e valore dell'URI del tuo database:

Quando si distribuisce l'applicazione, Spring utilizzerà tale valore di variabile d'ambiente. Abbiamo fatto i requisiti e continuiamo con la parte di implementazione.

4.2. Distribuzione con CLI

Per implementare il progetto, esegui un'attività di gradle build:

gradle build

Questa attività genererà un file di guerra chiamato ROOT.war. Copia questo file in una nuova cartella e installa CLI modulo se non lo hai.

npm install -g modulo

Accedi al sistema;

accesso modulo

Ora esegui il seguente comando per la distribuzione ROOT.war al modulo.

modulo distribuire

Questo distribuirà il file war e potrai tail dei log del progetto per vedere lo stato della tua implementazione eseguendo il seguente comando:

coda di registro modulo modulo

Questo è tutto con lo spiegamento!

5. conclusione

Lo scopo principale di questo tutorial è mostrarti come creare un'applicazione di chat in tempo reale con Spring Boot, WebSockets e MongoDB. 

Per eseguire il progetto in produzione, Modulus viene utilizzato come fornitore PaaS. Modulus ha passaggi molto semplici per la distribuzione e ha anche un database interno (MongoDB) per i nostri progetti. Oltre a questo, puoi utilizzare strumenti molto utili nel dashboard Modulus come Registri, Notifiche, Scalatura automatica, Amministrazione Db e altro ancora.